Parallelisieren Sie eine Funktion mit xargs und separaten Variablen

Parallelisieren Sie eine Funktion mit xargs und separaten Variablen

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 xargsdie Parallelisierung zu ermöglichen.UNDa=0Ich 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 -Iverschluckt -d/ -0immer noch Anführungszeichen und Backslashs und entfernt führende Leerzeichen. Mit GNU xargs(das Sie verwenden müssen, da Sie bereits die -PGNU-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 bashAufruf für jede 1Zeile der Eingabe mit dem Inhalt von $aund der aktuellen Zeile als separate Argumente auf, auf die im Inline-Shell-Skript als $1und 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, zshdas über eine zargsautomatisch 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 xargses 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

verwandte Informationen