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

1720
Simon O'Hanlon

Ich benutze die zshSchale. Ich versuche zu verwenden, sedum einige Texte in vielen Dateien zu ersetzen und parallel, um den Prozess zu beschleunigen. Als ich dies an einer Datei getestet hatte und die Befehlsausgabe auf gehen ließ, stdoutsah ich das erwartete Ergebnis. 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 einzige zusammengesetzte Datendatei zum Anschneiden ausgeschnitten und eingefügt 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
3

1 Antwort auf die Frage

3
Adaephon

Wenn Sie die Umleitung innerhalb des Befehls für verwenden parallel, müssen Sie {}die Eingabe an die richtige Stelle setzen, als Parameter für sed:

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

Wenn {//}(oder eine andere Ersatzzeichenfolge) verwendet wird, parallelhängt die Eingabe außerdem nicht automatisch am Ende des Befehls 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 
Nicht ganz korrekt: Wenn eine Ersatzzeichenfolge (z. B. {//}) verwendet wird, wird {} nicht _ angehängt. Der Code läuft also: sed "s / (^ 3. * 3 \) / \ 13 /"> ./result.txt (was eindeutig auch falsch ist. Bestätigen Sie mit --dry-run). Die Antwort von Adaephon ist also richtig, aber aus einem falschen Grund. Ole Tange vor 9 Jahren 1
@OleTange Danke fürs Heads-Up. Ich habe die Antwort entsprechend bearbeitet. Adaephon vor 9 Jahren 0