Wenn Sie sed mit parallel verwenden, erhalten Sie eine leere Ausgabe, wenn Sie in eine Datei umleiten

3

Ich benutze die zsh Schale. Ich versuche es zu benutzen sed um Text in vielen Dateien zu ersetzen, verwenden Sie parallel, um den Prozess zu beschleunigen. Wenn ich dies an einer Datei getestet habe und die Befehlsausgabe zu gehen lasse stdout Ich habe das erwartete Ergebnis gesehen. Als ich versuchte, diese Ausgabe in eine Datei umzuleiten, bekam ich eine leere Datei. Was ist los? Hier ist ein triviales Beispiel, bei dem eine einzelne Datendatei zum Ausschneiden und Einfügen verwendet wird.

setopt interactivecomments
#  In this trivial example it is obviously non-sensical
#  to use parallel, but in reality I have many files...

#  Some very simple input data...
paste <(printf "%s\n" `seq 1 4`) <(printf "%s\n" `seq 1 4`) > ./input.txt
#  This looks like:
#1       1
#2       2
#3       3
#4       4


#  Pass data file to parallel and use sed to substitute.
#  e.g. want to replace line '3 3' with '3 33'
#  Output goes to stdout & seems correct...
z=`find ./input.txt`
echo "$z" | parallel 'sed "s/\(^3.*3\)/\13/"'
#1       1
#2       2
#3       33    ===> correct replacement
#4       4

# But redirecting to a file leads to empty file...
echo "$z" | parallel 'sed "s/\(^3.*3\)/\13/" > {//}/result.txt'

# Empty file
cat ./result.txt

Was gibt? Muss ich etwas falsch angeben?

Ich benutze:

  • Ubuntu 12.04.4 LTS
  • GNU parallel 20130522
  • GNU sed version 4.2.1
  • zsh 4.3.17
Simon O'Hanlon
quelle

Antworten:

3

Bei Verwendung der Umleitung innerhalb des Befehls für parallelmusst du verwenden {} um die Eingabe an die richtige Stelle zu setzen, als Parameter für sed:

echo "$z" | parallel 'sed "s/\(^3.*3\)/\13/" {} > {//}/result.txt'

Zusätzlich, wenn {//} (oder eine andere Ersatzzeichenfolge) verwendet wird, parallel fügt die Eingabe am Ende des Befehls nicht automatisch an. (In diesem Fall wäre das ohnehin falsch, wie es nach der Umleitung der Fall wäre.)

Im Wesentlichen wird der Code in der Frage ausgeführt

sed "s/(^3.*3\)/\13/" > ./result.txt

aber es muss sein

sed "s/(^3.*3\)/\13/" ./input.txt > ./result.txt
Adaephon
quelle
1
Nicht ganz korrekt: Wenn eine Ersatzzeichenfolge (z. B. {//}) verwendet wird, wird {} verwendet nicht angehängt werden. Der Code läuft also: sed "s / (^ 3. * 3) / \ 13 /" & gt; ./result.txt (was natürlich auch falsch ist. Bestätigen Sie mit --dry-run). Die Antwort von Adaephon ist also richtig, aber aus einem falschen Grund.
Ole Tange
@OleTange Danke fürs Heads-Up. Ich habe die Antwort entsprechend bearbeitet.
Adaephon