Rohr B nach D? - A && B || C | D

14

Gibt es eine Möglichkeit, die Befehlsstruktur neu zu schreiben, A && B || C | Dsodass entweder B oder C in D weitergeleitet werden?

Mit dem aktuellen Befehl werden entweder nur B oder sowohl C als auch D ausgeführt.

Beispielsweise:

Bildbeschreibung hier eingeben

Philip Kirkbride
quelle

Antworten:

31

Ja, in bash können Sie Klammern verwenden:

(A && B || C) | D

Auf diese Weise der Ausgang A && B || Cwird in geleitet werden D.

utopisch
quelle
6
Oder A && (B || C) | Dwenn Sie nicht möchten, dass B, C oder D ausgeführt werden, wenn A ausfällt
zwol
2
Sie können auch parens in verwenden sh:)
EKons
Es ist unklar, ob die Verwendung von Klammern anstelle von geschweiften Klammern eine absichtliche Entscheidung war (wenn ja, welche Vorteile ergeben sich daraus?) Oder nur ein Versehen. Könntest du erklären?
Tom Fenech
@TomFenech Parens bewirken, dass der Ausdruck in einer Sub-Shell ausgeführt wird, die ein (einzelner) separater Prozess vom POV des restlichen Skripts ist. Unabhängig von der Ausgabe des Ausdrucks in parens wird er daher zusammen geleitet. (Da Asich in der Unterschale befindet, schließt dies auch ein A.)
jpaugh
1
@jpaugh Ich denke, deine Meinung zur Isolation ist gut, aber die Ausgabe würde bei Verwendung von geschweiften Klammern auf die gleiche Weise weitergeleitet, nicht wahr?
Tom Fenech
14

Sie können dies als schreiben

if A; then B; else C; fi | D

Du sagst, du willst entweder Boder laufen C, aber A && B || Cdas schaffst du nicht. Wenn dies Agelingt, aber ausgeführt wird Bund fehlschlägt, wird es ausgeführt C.

Hinweis 1: Wenn Sie irgendwie garantieren können, dass das Bimmer gelingt und Sie bei einer kurzen Version bleiben möchten, dann würde ich mich trotzdem dafür entscheiden

{ A && B || C; } | D

über ( ... ), da letztere unnötigerweise die Erzeugung einer neuen Unterschale erzwingt, die möglicherweise wegoptimiert wird oder nicht.

Anmerkung 2: Beide Formen gehen davon Aaus, dass keine Ausgabe erfolgt, was in Ihrem Beispiel zutrifft, aber nicht unbedingt im Allgemeinen. Das kann vermieden werden durch

A; if [ "$?" -eq 0 ]; then B; else C; fi | D
hvd
quelle
Sind Sie sicher, dass { … }aufgrund der Pipe keine Unterschale erstellt werden muss? Ich beobachte folgendes Verhalten: pgrep bashund pgrep bash | catund if true; then pgrep bash; fiund { pgrep bash; }haben eine Ausgabezeile; ( pgrep bash; )und ( pgrep bash; ) | catund { pgrep bash; } | catund if true; then pgrep bash; fi | cathaben zwei Ausgabezeilen.
wchargin
@wchargin ... | ...bewirkt, dass eine Subshell erstellt wird, was unvermeidlich ist. ( ... )Zumindest theoretisch wird eine zusätzliche Subshell erstellt, die dies { ...; }vermeidet, aber das habe ich mit "kann oder kann nicht optimiert werden" gemeint: Es ist möglich, dass in diesem speziellen Fall die Shell merkt, dass es keine Rolle spielt, die Wirkung wäre das gleiche.
HDV
5

Die accepter Antwort ist richtig , aber es ist nicht die mögliche Verwendung Fall Deckung nicht die Ausgabe haben Aals Eingang D. Um dies zu erreichen, müssen Sie Aje nach Bedarf eine Stream-Umleitung aktivieren.

  • Wenn Sie die Ausgabe Atrotzdem verwerfen möchten :

    { A >/dev/null && B || C; } | D
  • Wenn Sie die Ausgabe von Aauf dem Terminal sehen möchten :

    { A >/dev/tty && B || C; } | D
  • Wenn Sie die Ausgabe von Aals Eingabe eines nachfolgenden Befehls Ebenötigen, benötigen Sie eine zusätzliche Befehlsgruppe und eine Stream-Umleitung:

    { { A >&3 && B || C; } | D; } 3>&1 | E

Wenn Ihnen das alles zu dunkel erscheint (wie mir), empfehle ich Ihnen, die spezielle Shell-Variable für den Exit-Status von zu verwenden Aund damit zu arbeiten:

A
if [ $? -eq 0 ]; then
  B
else
  C
fi |
D

Wenn Sie prägnanter, aber nicht zu geheimnisvoll sein möchten, empfehle ich Folgendes:

A; { [ $? -eq 0 ] && B || C; } | D

(Siehe auch den letzten Teil der Antwort von hvd, den ich nicht bemerkt habe, als ich meine ursprüngliche Antwort geschrieben habe.)

David Foerster
quelle
Meine Antwort deckt das ab. Sehen Sie, was ich in meine "Anmerkung 2:" geschrieben habe, wo ich einfach Aaus der Pipeline herausgezogen bin .
HDV
@hvd: Du hast Recht und danke, dass du mir auf diesen Teil deiner Antwort hingewiesen hast! Ich habe meinen Anspruch geändert und dir die entsprechende Gutschrift gegeben.
David Foerster