Когда наследование _errexit не работает?

Как насчет того, чтобы просто использовать printfдля преобразования?

printf '^%x\n' 46390 | grep -f- file

(Я не думаю, что преобразование обоих в двоичный формат поможет)

3
20.10.2021, 14:24
1 ответ

TL,DR :, чтобы воспользоваться преимуществами set -e, напрямую присвоить результат подстановки команд переменной (, опционально с дополнительными строками вокруг нее ). Не объединяйте несколько подстановок команд вместе и не используйте подстановку команд в аргументе команды.

Проблема не в inherit_errexit. Это работает. Проблема заключается в ограничениях set -e(, которые не являются специфическими для bash :другие sh -подобные оболочки имеют ту же проблему ).

Демонстрация :Запустите этот вариант второго примера.

$ cat b2.sh 
#!/usr/bin/env bash
set -e
shopt -s inherit_errexit
echo -n $(cat no-such-file; echo >&2 after cat)
echo survived
$./b2.sh 
cat: no-such-file: No such file or directory
survived

Обратите внимание, что echo >&2 after catне было выполнено. Это было бы, если бы inherit_errexitбыл выключен.

Проблема в том, что set -eостанавливает выполнение при ошибке только в простых случаях. Если замена команды возвращает состояние ошибки, это не останавливает выполнение простой команды, содержащей замену. В лучшем случае он может установить статус возврата простой команды, которая, в свою очередь, может остановить выполнение скрипта. «Простая команда» состоит из заданий,перенаправления и необязательное имя исполняемой команды и аргументы. Если перенаправление завершается неудачно, статус возврата равен 1. В противном случае, если имеется имя команды, статус возврата простой команды является статусом возврата исполняемой команды. В противном случае статус возврата является статусом возврата последней подстановки команды или 0, если его нет. Вот несколько примеров простых команд:

  • true </no/such/file→ статус 1 из-за неудачного перенаправления
  • false </dev/null→ статус 1 изfalse
  • a=b→ статус 0 из-за отсутствия деталей, которые могут выйти из строя
  • a=$(exit 0) b=$(exit 1) c=$(exit 2)→ статус 2 от последней подстановки команды
  • a=$(exit 2) b=$(exit 1) c=$(exit 0)→ статус 0 с момента последней подстановки команды
  • true $(exit 0) $(exit 1) $(exit 2)→ статус 0 изtrue

Опять же, во всех случаях set -eостановит сценарий только в том случае, если статус команды не равен нулю. Статус встроенных команд не имеет прямого отношения.

Итак, во втором сценарии echo -n $(…)имеет статус 0 из echo(, за исключением случаев, когда echoне может записать ), независимо от того, что происходит внутри подстановки команды. Поэтому скрипт не остановится на этом, даже если активен set -e. Аналогично, в третьем скрипте f $(…)имеет статус 0 из f.

5
20.10.2021, 15:01

Теги

Похожие вопросы