Alternative für | (Rohr-) Betreiber

8

Ich suche nach einer Alternative für den |Operator in der Bash-Shell, um die Ausgabe des Befehls als Eingabe für den nächsten Befehl umzuleiten. Gibt es eine Alternative?

etwas wie :

command1 | command2 | command3

mit Alternative zu:

command1 X command2 X command3

Xwird anstelle von verwendet |. Ist es möglich, die Verwendung zu vermeiden |und durch den tatsächlichen Betreiber zu ersetzen?

αғsнιη
quelle
Wieso brauchst du es?
Choroba
@ Choroba ist das wichtig? Nur um die Verwendung zu vermeiden |.
αғsнιη
3
Ich überprüfe nur, dass es kein XY-Problem ist .
Choroba
3
@ KasiyA, ich verstehe den Zweck dieser Frage immer noch nicht. Versuchen Sie zu vermeiden, dass die Befehle in Subshells ausgeführt werden? Sind Sie von der Form der beleidigt |? Die zweite Frage ist snarky, aber welches Problem versuchen Sie zu lösen?
Glenn Jackman
Es ist immer noch nicht klar. Möchten Sie die Ausgabe des ersten Befehls duplizieren? Dann teemit Prozesssubstitution könnte das sein, was Sie brauchen.
Muru

Antworten:

14

Das Äquivalent von command1 | command2istcommand2 < <(command1)

Dies kann auch auf drei (oder mehr) Befehle erweitert werden.

command3 < <(command2 < <(command1))

$ lspci | grep 'Network'
 02:00.0 Network controller: Qualcomm Atheros AR9285 Wireless Network Adapter (PCI-Express) (rev 01)

$ grep 'Network' <(lspci)
 02:00.0 Network controller: Qualcomm Atheros AR9285 Wireless Network Adapter (PCI-Express) (rev 01)

$ lspci | grep 'Network' | grep -o 'controller'
 controller

$ grep -o 'controller' < <(grep 'Network' < <(lspci))
 controller

Wie Oli vorschlug, ist dies zwar technisch gesehen die gleiche Leistung wie eine Pipe.

<(..) verwandelt das STDOUT der internen Befehlsausgabe in einen Dateihandler (den der Befehl, in Ihrem Beispiel grep) öffnet. Wenn Sie eine Pipe ausführen, liest der Lesebefehl direkt aus STDIN (das mit STDOUT des Pipe-Befehls gefüllt wird). Subtile Unterschiede können jedoch bei Befehlen von Bedeutung sein, die nur STDIN lesen können.

Rohith Madhavan
quelle
4
Dies ist technisch nicht korrekt. <(..)verwandelt das STDOUT der internen Befehlsausgabe in einen Dateideskriptor (den der Befehl grepin Ihrem Beispiel öffnet). Wenn Sie eine Pipe ausführen, liest der Lesebefehl direkt aus STDIN (das mit STDOUT des Pipe-Befehls gefüllt wird). Subtile Unterschiede können jedoch bei Befehlen von Bedeutung sein, die nur STDIN lesen können.
Oli
bearbeitet mit Olis Vorschlag: cmd2 < <(cmd1)ist eher so.
Glenn Jackman
@Oli Fügte Ihren Kommentar zur Antwort hinzu, um den Unterschied hervorzuheben.
Rohith Madhavan
@Oli, ich bin nicht sicher, woher du diese Informationen hast, aber es scheint falsch zu sein. In beiden Fällen erstellt die Shell ein pipe(2)und fork()s und dup2()s das Rohr zum Standard des einen Prozesses und zum Standard des anderen. Der Unterschied scheint darin zu liegen, dass das Programm in Klammern in einer Unterschale ausgeführt wird. Wenn Sie beispielsweise Strg-C drücken, wird das Programm in der Unterschale nicht unterbrochen und geht "verloren". Das fühlt sich für mich tatsächlich wie ein Fehler an.
Psusi
1
Der Punkt ist , dass trotz der führenden, <ist dies nicht eine Umleitung. <()in einer Befehlszeile wird vollständig durch den Pfad zu einer Datei ersetzt, eine Datei, die zufällig die Standardausgabe des Befehls innerhalb der Prozessersetzung ist, aber dennoch ein Pfad. Ob Sie einen Pfad zu einer Datei angeben oder von (oder zu dieser, wenn >()) umleiten möchten, ist eine separate Frage. Deshalb ist dieser Prozess Substitution und nicht die Prozess Umleitung - wie Kommandosubstitution wird die Sache mit etwas ersetzt, einen Dateinamen in ein und Ausgang in den anderen.
Muru