it-swarm.com.de

bash: kürzester Weg, um die n-te Spalte der Ausgabe zu erhalten

Nehmen wir an, dass Sie während Ihres Arbeitstages wiederholt auf die folgende Form der kolumnisierten Ausgabe eines Befehls in bash stoßen (in meinem Fall von der Ausführung von svn st in meinem Rails Arbeitsverzeichnis):

?       changes.patch
M       app/models/superman.rb
A       app/models/superwoman.rb

um mit der Ausgabe Ihres Befehls - in diesem Fall den Dateinamen - zu arbeiten, ist eine Art Analyse erforderlich, damit die zweite Spalte als Eingabe für den nächsten Befehl verwendet werden kann.

Ich habe awk verwendet, um in die zweite Spalte zu gelangen, z. Wenn ich alle Dateien entfernen möchte (nicht, dass dies ein typischer Anwendungsfall ist :), würde ich Folgendes tun:

svn st | awk '{print $2}' | xargs rm

Da ich das sehr oft tippe, stellt sich natürlich die Frage: Gibt es einen kürzeren (also kühleren) Weg, dies in bash zu erreichen?

HINWEIS: Was ich stelle, ist im Wesentlichen eine Shell-Befehlsfrage, obwohl sich mein konkretes Beispiel in meinem SVN-Workflow befindet. Wenn Sie der Meinung sind, dass der Workflow albern ist und einen alternativen Ansatz vorschlägt, werde ich Sie wahrscheinlich nicht ablehnen, andere jedoch, da hier die Frage lautet, wie die Ausgabe des n-ten Spaltenbefehls in Bash auf kürzestmögliche Weise erfolgen kann . Vielen Dank :)

140
Sv1

Sie können cut verwenden, um auf das zweite Feld zuzugreifen:

cut -f2

Edit: Sorry, habe nicht bemerkt, dass SVN keine Tabs in seiner Ausgabe verwendet, also ist das ein bisschen nutzlos. Sie können cut an die Ausgabe anpassen, aber es ist ein bisschen zerbrechlich - so etwas wie cut -c 10- würde funktionieren, aber der genaue Wert hängt von Ihrem Setup ab.

Eine andere Option ist so etwas wie: sed 's/.\s\+//'

99
porges

Um dasselbe zu erreichen wie:

svn st | awk '{print $2}' | xargs rm

mit nur bash kannst du benutzen:

svn st | while read a b; do rm "$b"; done

Zugegeben, es ist nicht kürzer, aber ein bisschen effizienter und behandelt Leerzeichen in Ihren Dateinamen korrekt.

89
Rick Sladkey

Ich befand mich in der gleichen Situation und fügte diese Aliase zu meinem .profile Datei:

alias c1="awk '{print \$1}'"
alias c2="awk '{print \$2}'"
alias c3="awk '{print \$3}'"
alias c4="awk '{print \$4}'"
alias c5="awk '{print \$5}'"
alias c6="awk '{print \$6}'"
alias c7="awk '{print \$7}'"
alias c8="awk '{print \$8}'"
alias c9="awk '{print \$9}'"

Was mir erlaubt so etwas zu schreiben:

svn st | c2 | xargs rm
28
StackedCrooked

Probieren Sie die zsh. Es unterstützt Suffix-Alias, so dass Sie X in Ihrer .zshrc definieren können

alias -g X="| cut -d' ' -f2"

dann kannst du machen:

cat file X

Sie können noch einen Schritt weiter gehen und ihn für die n-te Spalte definieren:

alias -g X2="| cut -d' ' -f2"
alias -g X1="| cut -d' ' -f1"
alias -g X3="| cut -d' ' -f3"

dies gibt die n-te Spalte der Datei "file" aus. Sie können dies auch für die Ausgabe von grep oder weniger tun. Dies ist sehr praktisch und ein Killer-Feature des zsh.

Sie können noch einen Schritt weiter gehen und D folgendermaßen definieren:

alias -g D="|xargs rm"

Jetzt können Sie Folgendes eingeben:

cat file X1 D

um alle in der ersten Spalte der Datei "Datei" genannten Dateien zu löschen.

Wenn Sie die Bash kennen, ist das zsh bis auf einige neue Funktionen keine große Veränderung.

HTH Chris

15
Chris

Da Sie mit Skripten scheinbar nicht vertraut sind, finden Sie hier ein Beispiel.

#!/bin/sh
# usage: svn st | x 2 | xargs rm
col=$1
shift
awk -v col="$col" '{print $col}' "${@--}"

Wenn Sie dies in ~/bin/x Speichern und sicherstellen, dass sich ~/bin In Ihrem PATH befindet (das ist etwas, das Sie in Ihren .bashrc Einfügen können und sollten), haben Sie der kürzestmögliche Befehl zum allgemeinen Extrahieren der Spalte n; x n.

Das Skript sollte eine ordnungsgemäße Fehlerprüfung durchführen und eine Fehlerbehebung durchführen, wenn es mit einem nicht numerischen Argument oder der falschen Anzahl von Argumenten usw. aufgerufen wird. Aber die Erweiterung dieser essentiellen Version wird in Einheit 102 sein.

Möglicherweise möchten Sie das Skript erweitern, um einen anderen Spaltentrenner zuzulassen. Awk parst standardmäßig Eingaben in Felder mit Leerzeichen; Um ein anderes Trennzeichen zu verwenden, verwenden Sie -F ':', wobei : das neue Trennzeichen ist. Wenn Sie dies als Option für das Skript implementieren, wird es geringfügig länger, und ich überlasse dies dem Leser als Übung.


Verwendungszweck

Gegeben eine Datei file:

1 2 3
4 5 6

Sie können es entweder über stdin übergeben (indem Sie ein nutzloses cat nur als Platzhalter für etwas Nützlicheres verwenden);

$ cat file | sh script.sh 2
2
5

Oder geben Sie es als Argument für das Skript an:

$ sh script.sh 2 file
2
5

Hier geht sh script.sh Davon aus, dass das Skript im aktuellen Verzeichnis als script.sh Gespeichert ist. Wenn Sie es mit einem nützlicheren Namen irgendwo in Ihrem PATH speichern und es als ausführbar markieren, wie in den obigen Anweisungen beschrieben, verwenden Sie stattdessen offensichtlich den nützlichen Namen (und kein sh).

8
tripleee

Sie haben anscheinend bereits eine Lösung. Um die Sache zu vereinfachen, schreiben Sie Ihren Befehl einfach in ein Bash-Skript (mit einem kurzen Namen) und führen Sie diesen Befehl aus, anstatt ihn jedes Mal einzugeben.

5
Tarek Fadel

Wenn Sie mit der manuellen Auswahl der Spalte einverstanden sind, können Sie mit pick sehr schnell vorgehen:

svn st | pick | xargs rm

Gehen Sie einfach zu einer beliebigen Zelle in der 2. Spalte, drücken Sie c und drücken Sie dann enter

2
Bernardo Rufino

Beachten Sie, dass sich der Dateipfad nicht in der zweiten Spalte der SVN-Ausgabe befinden muss. Wenn Sie beispielsweise eine Datei ändern und ihre Eigenschaft ändern, handelt es sich um die dritte Spalte.

Mögliche Ausgabebeispiele finden Sie in:

svn help st

Beispielausgabe:

 M     wc/bar.c
A  +   wc/qax.c

Ich schlage vor, die ersten 8 Zeichen zu schneiden durch:

svn st | cut -c8- | while read FILE; do echo whatever with "$FILE"; done

Wenn Sie 100% sicher sein und sich beispielsweise mit ausgefallenen Dateinamen mit Leerzeichen am Ende befassen möchten, müssen Sie die XML-Ausgabe analysieren:

svn st --xml | grep -o 'path=".*"' | sed 's/^path="//; s/"$//'

Natürlich möchten Sie vielleicht einen echten XML-Parser anstelle von grep/sed verwenden.

1
Michał Šrajer