Когда конструкции if не требуют скобок?

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

if echo "$1" | grep -v ".*[^A-Za-z_]" > /dev/null
then
        echo yes
else
        echo no
fi

Я понимаю, что скобки - это сокращение для тестовой функции в оболочке BASH. Моя проблема в том, что когда я попытался выполнить приведенный выше скрипт с помощью скобок, я получил ошибку.

if [ echo "$1" | grep -v ".*[^A-Za-z_]" > /dev/null ]

Проблема с этим (я полагаю) заключается в том, что grep пытается использовать ] в качестве аргумента, что приводит к ошибке при запуске скрипта.

В каких случаях скобки не нужны?


person cerule    schedule 03.11.2014    source источник


Ответы (3)


[/test - это команда (также встроенная), как вы сказали. Это команда, которая принимает аргументы определенного типа и ведет себя определенным образом с учетом этих аргументов.

Он принимает флаги и операторы сравнения и работает с ними для получения результата true или false. Затем он переводит этот результат в код возврата. 0 вместо true и 1 вместо false.

Конструкция if в оболочке определена

если список; затем список; [список Элиф; затем список; ] ... [иначе список; ] фи

Список if выполняется. Если его статус выхода равен нулю, то выполняется список then. В противном случае каждый список elif выполняется по очереди, и если его статус выхода равен нулю, выполняется соответствующий список then и команда завершается. В противном случае выполняется список else, если он присутствует. Статус выхода — это статус выхода последней выполненной команды или ноль, если ни одно из условий не проверено.

Итак, когда [/test возвращает код выхода, это то, что оценивает if.

Причина, по которой вам не нужно (и вы не можете использовать) [ вокруг команды/конвейера echo, заключается в том, что это недопустимый набор аргументов [. Вместо этого это сама команда list, и поэтому ее не нужно оценивать с помощью [. Вы можете просто использовать его напрямую и передать код возврата конвейера if для оценки.

person Etan Reisner    schedule 04.11.2014
comment
Спасибо за ответ, последнее немного прояснило мое замешательство. Я не знал, что у команд есть коды возврата. - person cerule; 04.11.2014
comment
@xcerule Код возврата самой последней команды хранится в $?. Самый последний бит важен, так как он влияет на такие вещи, как 'some_complex_command; эхо-сообщение о состоянии; если [$? -ne 0]; затем ... fi`, который многие люди пробуют случайно, не осознавая, что они только что затерли код возврата своей сложной команды кодом возврата echo. Кроме того, код возврата конвейера — это код возврата последней команды в конвейере (независимо от того, что возвращает любая другая команда, но см. pipefail и переменную $PIPESTATUS на странице руководства bash для получения дополнительной информации). - person Etan Reisner; 04.11.2014

[ на самом деле является командой (она встроена в большинство оболочек), а не просто частью синтаксиса оператора if.

Оператор if выполняет команду, которая является его аргументом. Если эта команда успешна (устанавливает $? в ноль), то условие истинно; если оно не удается (устанавливает $? в какое-либо ненулевое значение), условие ложно.

Встроенная команда [ почти полностью эквивалентна команде test; разница в том, что [ требует ] в качестве последнего аргумента.

См. также https://unix.stackexchange.com/a/22728/10454.

person Keith Thompson    schedule 04.11.2014

Вы также можете использовать двойные квадратные скобки [[ вместо одинарных [

Подробнее об этом читайте здесь: http://mywiki.wooledge.org/BashFAQ/031:

[ ("test" command) and [[ ("new test" command) are used to
evaluate expressions. [[ works only in Bash, Zsh and the Korn shell,
and is more powerful; [ and test are available in POSIX shells
person Jotne    schedule 04.11.2014
comment
Хм, формат немного теряется при цитировании, трудно понять, как лучше форматировать. - person fedorqui 'SO stop harming'; 04.11.2014