GNU/Linux >> LINUX-Kenntnisse >  >> Linux

Ein Befehl, um jede Zeile vorwärts und dann rückwärts auszugeben

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

Linux
  1. Befehlszeilenprogramm zum Abrufen von Passwörtern ohne Echo?

  2. Bash-Skript:Wie weist man jede Zeile der Befehlsausgabe Werten in einem Array zu?

  3. Vob-Dateien über die Befehlszeile zusammenführen?

  4. Iteration über jede Zeile der Ausgabe von ls -l

  5. Ruft die erste Zeile der Ausgabe eines Shell-Befehls ab

Lolcat – Ein Befehlszeilentool zur Ausgabe von Rainbow Of Colors im Linux-Terminal

Bash las Befehl

Diff-Befehl unter Linux

Prettyping – Machen Sie die Ausgabe des Ping-Befehls schöner und leichter lesbar

So lesen Sie die Ausgabe und Verwendung von Linux Top Command

Wie liest man Befehlszeilenargumente in Shell-Skripten?