Czy istnieje sposób, aby ponownie napisać strukturę poleceń, A && B || C | D
aby B lub C zostały podłączone do D?
Przy bieżącym poleceniu uruchamiane są tylko B lub oba C i D.
Na przykład:
Czy istnieje sposób, aby ponownie napisać strukturę poleceń, A && B || C | D
aby B lub C zostały podłączone do D?
Przy bieżącym poleceniu uruchamiane są tylko B lub oba C i D.
Na przykład:
Odpowiedzi:
Tak, w bash możesz użyć nawiasów:
(A && B || C) | D
W ten sposób wyjście A && B || C
zostanie przekazane do D
.
sh
:)
A
znajduje się w podpowłoce, obejmuje to również A
.)
Możesz to napisać jako
if A; then B; else C; fi | D
Mówisz, że chcesz uruchomić albo B
albo C
, ale A && B || C
nie osiągnąć. Jeśli się A
powiedzie, ale B
uruchomi się i nie powiedzie, wykona się C
.
Uwaga 1: jeśli możesz w jakiś sposób zagwarantować, że B
zawsze się powiedzie i chcesz pozostać przy krótkiej wersji, nadal bym wybrał
{ A && B || C; } | D
koniec ( ... )
, ponieważ ten ostatni niepotrzebnie wymusza utworzenie nowej podpowłoki, która może, ale nie musi zostać zoptymalizowana.
Uwaga 2: zakładamy, że obie formy A
nie generują danych wyjściowych, co jest prawdą w twoim przykładzie, ale niekoniecznie w ogóle. Można tego uniknąć
A; if [ "$?" -eq 0 ]; then B; else C; fi | D
{ … }
nie wymusza to utworzenia podpowłoki z powodu potoku? I zaobserwować następujące zachowanie: pgrep bash
i pgrep bash | cat
i if true; then pgrep bash; fi
i { pgrep bash; }
mają jedną linię wyjścia; ( pgrep bash; )
i ( pgrep bash; ) | cat
i { pgrep bash; } | cat
i if true; then pgrep bash; fi | cat
mają dwa wiersze wyników.
... | ...
powoduje utworzenie podpowłoki, co jest nieuniknione. ( ... )
, przynajmniej teoretycznie, powoduje utworzenie dodatkowej podpowłoki, która { ...; }
pozwala jej uniknąć, ale właśnie to miałem na myśli mówiąc „może zostać zoptymalizowany lub nie”: możliwe jest, że w tym konkretnym przypadku powłoka zdaje sobie sprawę, że to nie ma znaczenia, efekt byłby taki sam.
Odpowiedź akceptora jest poprawna, ale nie obejmuje potencjalnego przypadku użycia, którego nie należy podawać A
jako wyniku D
. Aby to osiągnąć, konieczne będzie przekierowanie strumienia w A
zależności od potrzeb.
Jeśli A
mimo wszystko chcesz odrzucić dane wyjściowe :
{ A >/dev/null && B || C; } | D
Jeśli chcesz zobaczyć dane wyjściowe A
na terminalu:
{ A >/dev/tty && B || C; } | D
Jeśli potrzebujesz danych wyjściowych A
jako danych wejściowych kolejnego polecenia E
, potrzebujesz dodatkowej grupy poleceń i przekierowania strumienia:
{ { A >&3 && B || C; } | D; } 3>&1 | E
Jeśli to wszystko wydaje się zbyt tajemnicze (tak jak dla mnie), zalecamy użycie specjalnej zmiennej powłoki dla statusu wyjścia A
i pracę z tym:
A
if [ $? -eq 0 ]; then
B
else
C
fi |
D
Jeśli chcesz być bardziej zwięzły, ale nie zbyt tajemniczy, sugeruję to:
A; { [ $? -eq 0 ] && B || C; } | D
(Zobacz także ostatnią część odpowiedzi hvd, której nie zauważyłem, kiedy napisałem swoją pierwotną odpowiedź).
A
wyszedłem z rurociągu.
A && (B || C) | D
, jeśli nie chcesz, aby B, C lub D działały, gdy A zawiedzie