Не допускайте виходу греп у разі вилучення


29

Цей сценарій не лунає "після":

#!/bin/bash -e

echo "before"

echo "anything" | grep e # it would if I searched for 'y' instead

echo "after"
exit

Так само, якби я видалив -eопцію в рядку shebang, але я хотів би зберегти її, щоб мій сценарій зупинився, якщо є помилка. Я не вважаю, що греп не знайшов відповідності як помилку. Як я можу запобігти йому так різко виходити?


Це спостереження, призначене лише для розгляду. Можливо, логіку цього сценарію слід продумати ще раз. Якщо не важливо знайти рядок, навіщо його шукати? Визначення grep таке, що люди приймають рішення на основі присутності або відсутності рядка. Якщо вас не хвилює жоден спосіб, то це не важливо. Крім того, здається, -eви потурбуєтесь: настільки, що будь-яка проблема катастрофічна.
Андрій Фаланга

2
@AndrewFalanga Мені все одно, оскільки я фактично аналізую вміст, var=$(complex command | grep complex_pattern)який може бути нульовим (у такому випадку моя програма не повинна припинятися). Це просто закинутий сценарій, який змушує виникнути проблеми. Тут немає жодної метафізичної дупки в логіці, правда? ;)
iago-lito

Знаючи тепер, що ви мали намір зафіксувати вихід, уточнює деякі речі. Як було подано, це мене бентежило.
Ендрю Фаланга

Відповіді:


33
echo "anything" | grep e || true

Пояснення:

$ echo "anything" | grep e
### error
$ echo $?
1
$ echo "anything" | grep e || true
### no error
$ echo $?
0
### DopeGhoti's "no-op" version
### (Potentially avoids spawning a process, if `true` is not a builtin):
$ echo "anything" | grep e || :
### no error
$ echo $?
0

Значок "||" означає "або". Якщо перша частина команди "не вдається" (що означає "grep e" повертає ненульовий код виходу), то частина після "||" виконується, успішно і повертає нуль як код виходу ( trueзавжди повертає нуль).


3
Трохи коротша версія тієї самої, яка не закручується /bin/true: command || :(так у вашому випадку, set -e; grep 'needle' haystack || :).
DopeGhoti

1
@DopeGhoti, trueце вбудований в деякі оболонки (принаймні bash 4.3на RHEL)
iruvar

3
Неправильно, оскільки якщо перша команда не вдасться, вона приховає помилку. Правильне рішення повинно повернути нуль, якщо перша команда в трубі не виконана.
sorin

11

Надійний спосіб безпечно та необов’язково grep повідомляти:

echo something | grep e || [[ $? == 1 ]] ## print 'something', $? is 0
echo something | grep x || [[ $? == 1 ]] ## no output, $? is 0
echo something | grep --wrong-arg e || [[ $? == 1 ]] ## stderr output, $? is 1

Відповідно до посібника posix , код виходу 1 означає, що рядки не вибрані, а> 1 означає помилку.


1
Це має бути прийнятою відповіддю, оскільки він лише пригнічує попереджувальний код виходу (1), якщо grep нічого не знаходить, але він передає справжні помилки (коди виходу> 1). Інші рішення тут завжди пригнічують справжні помилки, що зазвичай погано.
HaroldFinch

7

Ще один варіант - додати в конвеєр ще одну команду - та, яка не виходить з ладу:

echo "anything" | grep e | cat

Оскільки catзараз остання команда в конвеєрі, то для виходу cat, grepякщо трубопровід вийшов з ладу чи ні, буде використовуватися статус виходу , а не з .



3

Рішення

#!/bin/bash -e

echo "before"

echo "anything" | grep e || : # it would if I searched for 'y' instead

echo "after"
exit

Пояснення

set -e або set -o errexit

Вийдіть негайно, якщо конвеєр (який може складатися з однієї простої команди ), списку або складеної команди (див. SHELL GRAMMARВище), виходить із ненульовим статусом. Оболонка не виходить , якщо команда , яка не є частиною списку команд відразу після появи whileабо untilключового слово, частина тесту , слідуючи ifабо elifзарезервовані слова, частина будь-якої команди , виконаної в &&або ||списку , крім команди після останньої &&або ||будь-який команда в конвеєрі, але остання, або якщо зворотне значення команди інвертується!. Якщо складна команда, яка не є допоміжною -eоболонкою, повертає ненульовий статус, оскільки команда не відбулася під час її ігнорування, оболонка не виходить. ERRЯкщо встановлено пастку , виконується до виходу оболонки. Цей параметр застосовується до середовища оболонки та кожного середовища під оболонки окремо (див. COMMAND EXECUTION ENVIRONMENTВище), і може призвести до виходу підпакетів перед виконанням всіх команд в підпакеті.

Плюс - :це команда без ефектів у Bash.

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