Eine Shell-Funktion. Dies funktioniert in jeder Shell, die <<<
unterstützt here-strings, einschließlich zsh und bash.
xyz() {
while read line
do
printf "%s " "$line"
"[email protected]" <<<"$line"
done
}
$ (echo "foo"; echo "bar") | xyz rev
foo oof
bar rab
In den meisten Fällen wird es aufgrund der Art und Weise, wie die stdio-Pufferung funktioniert, viele Probleme geben. Eine Problemumgehung für Linux könnte die Verwendung von stdbuf
sein program und führen Sie den Befehl mit coproc aus, damit Sie die Verschachtelung der Ausgabe explizit steuern können.
Im Folgenden wird davon ausgegangen, dass der Befehl eine Zeile nach jeder Eingabezeile ausgibt.
#!/bin/bash
coproc stdbuf -i0 -o0 "[email protected]"
IFS=
while read -r in ; do
printf "%s " "$in"
printf "%s\n" "$in" >&${COPROC[1]}
read -r out <&${COPROC[0]}
printf "%s\n" "$out"
done
Wenn eine allgemeinere Lösung benötigt wird, da das OP nur jede Zeile der Eingabe in das Programm irgendwann benötigt statt sofort eine Zeile ausgeben, dann ist ein komplizierterer Ansatz erforderlich. Erstellen Sie eine Ereignisschleife mit read -t 0
zu versuchen und von stdin und dem Co-Prozess zu lesen, wenn Sie die gleiche "Zeilennummer" für beide haben, dann geben Sie sie aus, andernfalls speichern Sie die Zeile. Um zu vermeiden, dass 100 % der CPU verwendet werden, wenn in einer Runde der Ereignisschleife keiner bereit war, führen Sie eine kleine Verzögerung ein, bevor Sie die Ereignisschleife erneut ausführen. Es gibt zusätzliche Komplikationen, wenn der Prozess Teilzeilen ausgibt, diese müssen gepuffert werden.
Wenn diese allgemeinere Lösung benötigt wird, würde ich dies mit Expect schreiben, da es bereits eine gute Unterstützung für den Umgang mit Musterabgleich bei mehreren Eingabeströmen bietet. Dies ist jedoch keine bash/zsh-Lösung.
In diesem speziellen Fall würde ich perl
verwenden :
printf '%s\n' foo bar | perl -Mopen=locale -lpe '$_ .= " " . reverse$_'
foo oof
bar rab
Was Sie erweitern könnten, um auch mit Graphem-Clustern zu arbeiten:
$ printf '%s\n' $'complique\u301' |
perl -Mopen=locale -lpe '$_ .= " " . join "", reverse/\X/g'
compliqué éuqilpmoc
Oder zsh
:
while IFS= read -r line; do
print -r -- $line ${(j::)${(s::Oa)line}}
done
Obwohl ich die Verwendung von while read
vermeiden würde Schleifen, um Text zu verarbeiten, sogar in zsh
(auch wenn es in diesem speziellen Fall nicht so schlimm ist, da nur eingebaute Befehle verwendet werden).
Im Allgemeinen ist die Verwendung von temporären Dateien wahrscheinlich der beste Ansatz. Mit zsh
, können Sie es tun mit:
(){paste -d ' ' $1 <(rev <$1)} =(print -l foo bar)
(wobei =(...)
kümmert sich um das Erstellen und Bereinigen der temporären Datei).
Ersetzen Sie es durch Pipes und eine Form von tee
ing ist ein Rezept für Deadlock im allgemeinen Fall. Sehen Sie sich diese ähnlichen Fragen für einige Ansätze und Details zu Deadlock-Situationen an:
- Aufteilen einer Eingabe für verschiedene Befehle und Kombinieren des Ergebnisses
- tee + cat:eine Ausgabe mehrfach verwenden und dann Ergebnisse verketten