Элегантный способ записи кода завершения команды в сценарии set-e

#bash

Вопрос:

У меня есть скрипт, обычно работающий под set -e (в частности, set -euo pipefail ).

Одна конкретная команда grep , я ожидаю , что иногда будет возвращать ненулевой код выхода, и я хочу предпринять некоторые действия в зависимости от конкретного кода возврата, а не просто от того, не удалась ли команда 1.

Что-то вроде:

 grep ...
if [[ $? -eq ... ]]; then
  ...
fi
 

Это не сработает, set -e если grep возвращает ненулевой код выхода, поэтому я никогда не доберусь до своего if . Я не могу просто запустить его напрямую в if подобном if grep ...; then режиме, так как меня волнует нечто большее, чем просто 0 и ненулевое.

Я не хочу временно отключаться set -e , так как это странно и нарушает состояние e на случай, если я не работал set -e в первую очередь.

Вот что я придумал:

 { grep ...; gexit=$?; } || true
if [[ $gexit -eq ... ]]; then
...
 

Конечно, должно быть что-то лучше?


1, в частности, grep немного необычен тем, что он возвращает код выхода 0, 1 или 2 для «1 совпадений», «0 совпадений» и «ошибка» соответственно. Однако я не ищу ответ, специфичный для grep.

Ответ №1:

Зависит от того, как вы определяете элегантность. Для меня это элегантно:

 if
  grep ...
  [[ $? -eq ... ]]
then
  ...
 

Но не очень полезно, так как статус выхода grep немедленно теряется и не может быть изучен дальше. С другой стороны, в этом нет такой проблемы:

 if grep ...; then
  # handle zero
  ...
else
  # handle non-zero
  case $? in
  ...)
    ...
  esac
fi
 

Ответ №2:

Это произойдет в режиме set-e, если grep вернет ненулевой код выхода, поэтому я никогда не доберусь до своего if

Проверка grep команды и ее аргументов внутри if инструкции не завершается сразу с set -e включенным режимом, даже если состояние выхода grep не равно нулю

 #!/usr/bin/env bash

set -e

if grep -q somestring somefile; then
  echo good
else
  echo bad
fi
 

Я проверил и то и другое с bash dash помощью и.

Комментарии:

1. Как я уже упоминал в вопросе, я не просто хочу проверить результат grep в 0/ненулевом смысле, потому что grep странный и использует несколько кодов выхода (0, 1 и 2), чтобы означать разные вещи. Поэтому я хочу записать точный код выхода, чтобы я мог провести дальнейшие сравнения. Я обновил вопрос, чтобы сделать это более понятным.