GNU Parallel entfernt Escape vor Leerzeichen im Befehl

GNU Parallel entfernt Escape vor Leerzeichen im Befehl

Ich teste derzeit GNU Parallel, um einen Vergleichsbefehl mit Bash auf mehrere Server zu verteilen. In seiner grundlegendsten Funktion benötigt dieser Vergleichsbefehl zwei zu vergleichende Eingaben (Oracle-Datenbankzugriffe) und erfordert einen Ausgabedateinamen über -o. Das Programm erfordert mindestens eine Aktion zum Laden, Speichern oder direkten Hochladen.

compare -o cmp.input1.input2.dat Input1 Input2

Ich habe ein paar Tausend dieser Eingabepaare und erstelle eine Datei mit allen Kombinationen, so dass jede Zeile den Ausgabedateinamen und die vom Programm benötigten Datenbankkennungen enthält

#test_parallel
-o cmp.input1.input2.dat Input1 Input2
-o cmp.input1.input3.dat Input1 Input3
-o cmp.input2.input3.dat Input2 Input3
[...]

und führen Sie den Befehl parallel aus, der Vergleichsbefehl schlägt jedoch fehl

parallel -a test_parallel "compare {}"
ERROR: No action specified for results (load, save or direct upload)
usage: compare [-u][-o <file>] query target

Mit --dryrundem Modus wird Folgendes parallel ausgeführt:

compare -o\ cmp.input1.input2.dat\ Input1\ Input2

Aus einem Grund, den ich nicht verstehe, werden die maskierten Leerzeichen vom Vergleichsprogramm nicht richtig verarbeitet. Das Ausführen dieses Befehls in Bash führt zu genau derselben Fehlermeldung. Das Entfernen des Escape nach dem Flag -o (ich könnte das -o in den parallelen Befehl verschieben) führt zu einem „zu viele Argumente“-Fehler. Das Entfernen aller Escapes führt den Befehl wie erwartet aus.

Ist es möglich, parallel anzuweisen, das Escape-Zeichen beim Befehlsaufruf nicht auszugeben? Ich finde in der Dokumentation nichts, außer dass dies das erwartete Standardverhalten ist, wie angegeben durchparallel --shellquote

Antwort1

GNU Parallel behandelt die Eingabe als einzelnes Argument und setzt sie in Anführungszeichen, sodass Sie Dateinamen wie die folgenden sicher verwenden können:

My brother's 12" records costs 30$ each.txt

In Ihrem Fall möchten Sie, dass das Argument von der Shell analysiert wird, daher werden die Leerzeichen nicht in Anführungszeichen gesetzt:

parallel -a test_parallel eval compare {}

Oder Sie können nach Speicherplatz aufteilen:

parallel --colsep ' ' -a test_parallel compare {1} {2} {3} {4}

Da Sie aber alles mit allem vergleichen möchten, können Sie dies viel eleganter tun:

parallel cmp -o ../out/cmp.{1}.{2} {1} {2} ::: Input* ::: Input*

Dadurch werden alle Eingaben* mit allen Eingaben* verglichen. Mit --resultskönnen Sie die Ausgaben schön strukturiert in einem Verzeichnis erhalten:

parallel --results out/ cmp {1} {2} ::: Input* ::: Input*

cmp InputY InputXWenn Sie das Laufen nach dem Laufen jedoch überspringen möchten cmd InputX InputY, können Sie Folgendes tun:

parallel --results out/ cmp {=1' $arg[1] ge $arg[2] and $job->skip();' =} {2} ::: Input* ::: Input*

Bearbeiten:

Die Version 20190722 führt die Funktion ein uq.

parallel -a test_parallel compare {=uq=}

uqist eine Perl-Funktion. Beim Aufruf wird GNU Parallel die Ersetzungszeichenfolge nicht in Anführungszeichen setzen. Sie können Ersetzungszeichenfolgen also in Anführungszeichen und ohne Anführungszeichen mischen:

parallel echo {} = {=uq=} ::: \$PWD
# You can change $_ if you want: uq() is a normal perl function
parallel echo {}ME = '{=uq(); $_.="ME"=}' ::: \$HO \$LOGNA

verwandte Informationen