Ich möchte einen Java-Befehl einmal für jedes Match von ausführen ls | grep pattern -
. In diesem Fall, denke ich, könnte ich tun, find pattern -exec java MyProg '{}' \;
aber ich bin neugierig auf den allgemeinen Fall - gibt es eine einfache Möglichkeit zu sagen: "Führen Sie einen Befehl einmal für jede Zeile der Standardeingabe aus"? (In Fisch oder Bash.)
162
printf "foo bar\nbaz bat" | xargs echo whee
wird nachgebenwhee foo bar baz bat
. Vielleicht die-L
oder-n
Optionen hinzufügen ?Die akzeptierte Antwort hat die richtige Idee, aber der Schlüssel ist,
xargs
den-n1
Schalter zu übergeben, was bedeutet, dass der Befehl einmal pro Ausgabezeile ausgeführt wird:Oder für eine einzelne Eingabedatei können Sie die Pipe
cat
ganz vermeiden und einfach mit gehen:quelle
xargs
, nicht ausgeführt zu werden, wennstdin
leer ist--no-run-if-empty
-r
:: Wenn die Standardeingabe keine Nicht-Leerzeichen enthält, führen Sie den Befehl nicht aus. Normalerweise wird der Befehl einmal ausgeführt, auch wenn keine Eingabe erfolgt. Diese Option ist eine GNU-Erweiterung.command
?In Bash oder einer anderen Bourne-Shell (ash, ksh, zsh,…):
read -r
Liest eine einzelne Zeile von der Standardeingabe (read
ohne-r
interpretierte Backslashes, das wollen Sie nicht). Somit können Sie eine der folgenden Aktionen ausführen:quelle
tail -f syslog | grep -e something -e somethingelse| while read line; do echo $line; done
, funktionierte es nicht. Es funktionierte mit einer Datei, die in diewhile
Schleife geleitet wurde. Es funktionierte nurtail -f
mit dergrep
, aber nicht mit beiden Pipes. Die Angabegrep
der--line-buffered
Option machte es Arbeitcommand | while read -r line; do echo "$line" | command ; done
Ich stimme Keith zu, xargs ist das allgemeinste Werkzeug für diesen Job.
Normalerweise benutze ich einen dreistufigen Ansatz.
Es gibt kleinere und schnellere Wege, aber diese Wege funktionieren fast immer.
Ein einfaches Beispiel:
In den ersten beiden Zeilen werden einige Dateien ausgewählt, mit denen gearbeitet werden soll. Anschließend bereitet awk einen schönen String mit einem auszuführenden Befehl und einigen Argumenten vor. $ 1 ist die erste Spalteneingabe aus der Pipe. Und schließlich stelle ich sicher, dass xargs diesen String an bash sendet, der ihn gerade ausführt.
Es ist ein bisschen übertrieben, aber dieses Rezept hat mir an vielen Stellen geholfen, da es sehr flexibel ist.
quelle
xargs -0
das Null-Byte als Trennzeichen fürprintf("MyJavaProg --args \"%s\"\0",$1)
awk
, können Sie es das Muster Match tun und überspringen diegrep
zBls | awk '/xls/ {print...
GNU Parallel ist für diese Art von Aufgaben gemacht. Die einfachste Verwendung ist:
Sehen Sie sich das Intro-Video an, um mehr zu erfahren: http://www.youtube.com/watch?v=OpaiGYxkSuQ
quelle
cat
hier, dagrep
kann direkt die Datei lesen< stuff grep pattern
abergrep pattern stuff
ohne Umleitung oder Katze überhaupt benötigt wird. Das ändert jedoch nichts an Ihrem Argument und wenn Sie der Meinung sind, dass es klarer ist, Dinge immer in einer Pipe zu verwenden, die mit beginntcat
, dann haben Sie die MachtAuch eine
while read
Schleife in der Fischschale (ich nehme an, Sie möchten eine Fischschale, wenn Sie ein Fischschild verwenden ).Einige Punkte zu beachten.
read
Es werden keine-r
Argumente verwendet und keine umgekehrten Schrägstriche interpretiert, um den häufigsten Anwendungsfall zu vereinfachen.$line
, da Fische im Gegensatz zu bash Variablen nicht durch Leerzeichen trennen.command
an sich ist ein Syntaxfehler (um die Verwendung von Platzhalterargumenten abzufangen). Ersetzen Sie es durch den echten Befehl.quelle
while
mitdo
& gepaart werdendone
anstattend
?Wenn Sie steuern müssen, wo genau das Eingabeargument in Ihre Befehlszeile eingefügt wird, oder wenn Sie es mehrmals wiederholen müssen, müssen Sie verwenden
BEISPIEL 1xargs -I{}
.Erstellen Sie eine leere Ordnerstruktur
BEISPIEL 2another_folder
, die die Unterordner im aktuellen Verzeichnis widerspiegelt:Wenden Sie eine Operation auf eine Dateiliste von stdin an. Erstellen Sie in diesem Fall eine Kopie jeder
.html
Datei, indem Sie eine.bak
Erweiterung anhängen :Von der
xargs
Manpage für MacOS / BSD :Linux-
xargs
Manpage :quelle
Wenn ich mit potenziell nicht bereinigten Eingaben zu tun habe, möchte ich, dass der gesamte Auftrag zeilenweise zur visuellen Überprüfung "ausgeschrieben" wird, bevor ich ihn ausführe (insbesondere, wenn er destruktiv ist, beispielsweise wenn die Postfächer von Personen gesäubert werden).
Ich erstelle also eine Liste von Parametern (z. B. Benutzernamen) und füttere sie zeilenweise in eine Datei:
Dann öffne ich die Liste in
vim
und zerfleische sie mit Suchen und Ersetzen-Ausdrücken, bis ich eine Liste der vollständigen Befehle erhalte, die ausgeführt werden müssen, wie folgt:Auf diese Weise können Sie bei unvollständigem regulären Ausdruck feststellen, bei welchem Befehl potenzielle Probleme auftreten (z. B.
/bin/rm -fr johnnyo connor
). Auf diese Weise können Sie Ihren regulären Ausdruck rückgängig machen und es mit einer zuverlässigeren Version erneut versuchen. Die Namensverfälschung ist dafür berüchtigt, weil es schwierig ist, sich um alle Randfälle wie Van Gogh, O'Connors, St. Clair und Smith-Wesson zu kümmern.Nachdem
set hlsearch
ist dies dafür nützlichvim
, da es alle Spiele werden markieren, so dass Sie leicht erkennen , wenn es nicht in unbeabsichtigter Weise oder Streichhölzer überein.Sobald Ihre Regex perfekt ist und alle Fälle erfasst, auf die Sie testen / denken können, konvertiere ich sie normalerweise in einen sed-Ausdruck, damit sie für einen weiteren Durchlauf vollständig automatisiert werden kann.
In Fällen, in denen die Anzahl der Eingabezeilen eine visuelle Überprüfung verhindert, empfehle ich dringend, den Befehl vor der Ausführung auf dem Bildschirm (oder besser noch in einem Protokoll) wiederzugeben. Wenn ein Fehler auftritt, wissen Sie genau, welcher Befehl verursacht wurde es zu scheitern. Dann können Sie zu Ihrem ursprünglichen regulären Ausdruck zurückkehren und ihn erneut anpassen.
quelle
Wenn ein Programm die Pipe ignoriert, aber Dateien als Argumente akzeptiert, können Sie es einfach auf die spezielle Datei verweisen
/dev/stdin
.Ich bin nicht mit Java vertraut, aber hier ist ein Beispiel, wie Sie es für Bash tun würden:
Das $ ist notwendig, damit Bash
\n
in Zeilenumbrüche übersetzt werden kann. Ich bin mir nicht sicher warum.quelle
Ich bevorzuge dies - mehrzeilige Befehle und eindeutigen Code zulassen
Siehe https://stackoverflow.com/a/3891678/248616
quelle
Hier eine Copypaste, die Sie sofort verwenden können:
Das Element aus der Liste wird dort abgelegt, wo sich das {} befindet, und der Rest des Befehls und der Parameter werden unverändert verwendet.
quelle