Как извлечь статус выхода команды в переменную?

14

Я начал изучать Bash пару дней назад.

Я пытаюсь получить статус выхода grepвыражения в переменную, как это:

check=grep -ci 'text' file.sh

и вывод, который я получил,

No command '-ic' found

Должен ли я сделать это с помощью команды pipe?

Омри Гилхар
источник
6
Статус выхода вы можете проверить $?сразу после завершения команды.
CoffeMug
и вы можете проверить массив PIPESTATUS, если хотите узнать состояние одной из команд в конвейере.
Cas

Ответы:

26

Ваша команда,

check=grep -ci 'text' file.sh

будет интерпретатором как «запустить команду -ciс аргументами textи file.sh, и установите значение переменной checkна значение grepв своей среде».


Оболочка хранит значение переменной последней выполненной команды в переменной ?. Вы можете присвоить его значение одной из ваших собственных переменных, например так:

grep -i 'PATTERN' file
check=$?

Если вы хотите воздействовать на это значение, вы можете использовать свою checkпеременную:

if [ "$check" -eq 0 ]; then
    # do things for success
else
    # do other things for failure
fi

или вы можете пропустить, используя отдельную переменную и проверяя $?все вместе:

if grep -q -i 'pattern' file; then
  # do things (pattern was found)
else
  # do other things (pattern was not found)
fi

(обратите внимание -q, что он инструктирует grepничего не выводить и выходить, как только что-то совпадает; нас на самом деле не интересует, что здесь совпадает)

Или, если вы просто хотите «делать что-то», когда шаблон не найден:

if ! grep -q -i 'pattern' file; then
  # do things (pattern was not found)
fi

Сохранение $?в другую переменную необходимо только в том случае, если вам нужно использовать его позже, когда значение в $?было перезаписано, как в

mkdir "$dir"
err=$?

if [ "$err" -ne 0 ] && [ ! -d "$dir" ]; then
    printf 'Error creating %s (error code %d)\n' "$dir" "$err" >&2
    exit "$err"
fi

В приведенном фрагменте кода, $?будет перезаписан результат [ "$err" -ne 0 ] && [ ! -d "$dir" ]теста. Сохранение здесь действительно необходимо, только если нам нужно отобразить его и использовать с exit.

Кусалананда
источник
4

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

grep -ci 'text' file.sh
check=$?

При выполнении команды из оболочки, ее статус выхода становится доступным через специальный параметр оболочки $?.

Это задокументировано POSIX (стандартом для Unix-подобных операционных систем) в его спецификации для оболочки, а реализация Bash задокументирована в разделе « Специальные параметры» .

Поскольку вы новичок, я настоятельно рекомендую вам начать с хорошей книги и / или онлайн-учебника, чтобы получить основы. Рекомендации внешних ресурсов не рекомендуются на сайтах Stack Exchange, но я бы предложил Lhunath и GreyCat's Bash Guide .

Энтони Геогеган
источник
4

Вы сказали bash установить переменную check=grepв среде, которую она передает команде

-ci 'text' file.sh

но ciне существует.

Я полагаю, что вы хотели заключить эту команду в обратные тики или в круглые скобки, перед которыми стоит знак доллара, причем любой из них назначил бы количество строк, на которых было найдено «текст» (без учета регистра) в файле:

check=`grep -ci 'text' file.sh`

check=$(grep -ci 'text' file.sh)

Теперь $checkдолжно быть 0, если совпадений нет, или положительное, если совпадений было.

Монти Хардер
источник
1

Запутался, зачем использовать -c при проверке вывода? Он используется для проверки того, сколько раз что-то совпало - нет, успешно это или нет.

   -c, --count
          Suppress normal output; instead print a count of matching  lines
          for  each  input  file.  With the -v, --invert-match option (see
          below), count non-matching lines.  (-c is specified by POSIX.)

но в этом примере

check="$(grep --silent -i 'text' file.sh; echo $?)"

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

Вы можете заменить --silent на -q. Я использую его, поскольку вы не заинтересованы в выводе grep, просто работает он или нет.

   -q, --quiet, --silent
          Quiet;  do  not  write  anything  to  standard   output.    Exit
          immediately  with  zero status if any match is found, even if an
          error was detected.  Also see the -s  or  --no-messages  option.
          (-q is specified by POSIX.)

$ check=$(echo test | grep -qi test; echo $?) # check variable is now set
$ echo $check
0
$ check=$(echo null | grep -qi test; echo $?)
$ echo $check
1
Miati
источник
1

Правильный способ присвоения выходных данных команды grep переменной: @ monty-hardder:

check=`grep -ci 'text' file.sh`
check=$(grep -ci 'text' file.sh)

Однако, чтобы назначить статус выхода этой команды переменной, вы должны использовать параметр оболочки $?сразу после выполнения команды, как показано ниже:

grep -ci 'text' file.sh
check=$?
echo $check
любознательный
источник