Труба від B до D? - A&& B || C | D


14

Чи є спосіб переписати командну структуру, A && B || C | Dщоб або B, або C було переведено в D?

За допомогою поточної команди виконується лише B або обидва C і D.

Наприклад:

введіть тут опис зображення

Відповіді:


31

Так, в bash ви можете використовувати дужки:

(A && B || C) | D

Таким чином, вхід A && B || Cбуде зафіксований D.


6
Або A && (B || C) | Dякщо ви не хочете, щоб B, C або D запускалися, коли A не
вдалося

2
Ви також можете використовувати парени у sh:)
EKons

Незрозуміло, чи використання дужок замість фігурних дужок було умисним рішенням (якщо так, то які переваги?) Чи просто недоглядом. Чи можете ви пояснити?
Том Фенек

@TomFenech Parens змушує вираз запускатись у підколонці, що є (єдиним) окремим процесом від POV решти сценарію. Тому, незалежно від виразу виразу всередині паролів, він буде з'єднаний. (Оскільки він Aзнаходиться всередині A
нижньої частини корпусу

1
@jpaugh Я думаю, що ваша думка про ізоляцію хороша, але вихід буде прокладений так само при використанні фігурних дужок, чи не так?
Том Фенех

14

Ви можете написати це як

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

Ви кажете, що хочете бігти Bабо C, але A && B || Cцього не досягаєте. Якщо це Aвдасться, але Bпробігає і не вдається, воно виконаєC .

Примітка 1: якщо ви можете якось гарантувати, що Bзавжди успішно і хочете дотримуватися короткої версії, я б все-таки вибрав це

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

над ( ... ) , оскільки останній необгрунтовано змушує створити нову підзарядку, яка може або не може бути оптимізованою.

Примітка 2: обидві форми припускають, що Aне дає результатів, що є правдою у вашому прикладі, але не обов'язково в цілому. Цього можна уникнути

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

Ви впевнені, що { … }не змушує створити підзаглушку через трубу? Я спостерігаю наступне поведінка: pgrep bashі pgrep bash | catта if true; then pgrep bash; fiі { pgrep bash; }мають один рядок; ( pgrep bash; )і ( pgrep bash; ) | catі { pgrep bash; } | catі if true; then pgrep bash; fi | catмають два рядки виведення.
wchargin

@wchargin ... | ...спричиняє створення додаткової оболонки , що неминуче. ( ... ), принаймні теоретично, спричиняє створення додаткової оболонки, яка { ...; }уникає, але саме це я мав на увазі "може або не може бути оптимізований": можливо, що в цьому конкретному випадку оболонка розуміє, що це не має значення, ефект був би таким же.
hvd

5

Відповідь приймача є правильною, але вона не охоплює потенційний випадок використання, щоб не мати вихід Aяк вхід D. Для цього вам потрібно перенаправлення потоку Aзалежно від ваших потреб.

  • Якщо ви хочете все-таки відкинути вихід A:

    { A >/dev/null && B || C; } | D
  • Якщо ви хочете побачити вихід Aтерміналу:

    { A >/dev/tty && B || C; } | D
  • Якщо вам потрібен вихід Aяк вхід наступної команди, Eвам знадобиться додаткова командна група та перенаправлення потоку:

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

Якщо все це здається вам занадто прихованим (як і мені), я рекомендую вам використовувати спеціальну змінну оболонки для стану виходу Aта працювати з цим:

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

Якщо ви хочете бути більш стислими, але не надто несерйозними, пропоную це:

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

(Дивіться також останню частину відповіді hvd, яку я не помітив, коли писав оригінальну відповідь.)


Моя відповідь охоплює це. Подивіться, що я помістив у своїй "Примітці 2:", де я просто Aвийшов з конвеєра.
hvd

@hvd: Ви правильні і дякую, що вказали на цю частину вашої відповіді на мене! Я змінив свою претензію і, відповідно, надав вам кредит.
Девід Фоерстер
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.