
Ich habe eine vierzeilige Textdatei mit 1, 2, 3 und 4 in jeder Zeile. Außerdem habe ich eine Funktion, die ich parallelisieren möchte:foo() { echo "$1 is not $2"; }
Ich exportiere die Funktion:export -f foo
Nun möchte ich die Funktion mit Parametern aus den Textdateien aufrufen, um xargs
die Parallelisierung zu ermöglichen.UNDa=0
Ich möchte auch eine Variable ( ) als Parameter in der Funktion verwenden . Daher würde ich die Funktion folgendermaßen aufrufen:cat txt | xargs -I "{}" -P 2 bash -c 'foo {} $a'
ABERDies ignoriert die Variable ( a=0
). Und gibt aus:
„1 ist nicht“ ... „4 ist nicht“ usw.
Wenn ich aufrufe: cat txt | xargs -I "{}" -P 2 bash -c 'foo {} 0'
es funktioniert und ich bekomme die richtige Ausgabe
„1 ist nicht0" ... "4 ist nicht0" usw
Aber ich muss es mit der Variable ( a=0
) aufrufen und nicht mit Null. Wie kann ich das machen?
Antwort1
Das Einbetten {}
in den Shell-Code ist immer keine gute Idee, da dadurch eine Schwachstelle durch Befehlsinjektion entsteht. Es ist immer besser, Daten als separate (nicht-Code-)Argumente zu übergeben.
Außerdem -I
verschluckt -d
/ -0
immer noch Anführungszeichen und Backslashs und entfernt führende Leerzeichen. Mit GNU xargs
(das Sie verwenden müssen, da Sie bereits die -P
GNU-Erweiterung verwenden) ist es am besten, -d '\n'
jede Eingabezeile als separates Argument zu übergeben.
xargs -a txt -rd'\n' -P2 -n1 bash -c 'foo "$2" "$1"' bash "$a"
(ruft einen bash
Aufruf für jede 1
Zeile der Eingabe mit dem Inhalt von $a
und der aktuellen Zeile als separate Argumente auf, auf die im Inline-Shell-Skript als $1
und verwiesen wird).$2
Oder mit -I
:
xargs -a txt -rd'\n' -P2 -I'{}' bash -c 'foo "$1" "$2"' bash {} "$a"
Hier können Sie zu wechseln, zsh
das über eine zargs
automatisch ladbare Funktion verfügt, die eine parallele Verarbeitung à la GNU durchführen kann xargs
, einschließlich Funktionen, ohne dass separate Shell-Aufrufe ausgeführt oder Funktionen exportiert werden müssen, wie xargs
es bei tut.
$ autoload zargs
$ foo() print -r - $1 is not $2
$ zargs -P2 -I {} {1..4} -- foo {} $a
1 is not foo
2 is not foo
3 is not foo
4 is not foo
Antwort2
Mit GNU Parallel sieht es folgendermaßen aus:
foo() { echo "$1 is not $2"; }
export -f foo
seq 4 > txt
a=0
cat txt | parallel foo {} $a