В том сабреддите хорошо смотрелась бы команда
[ -z $var
]
.Это конструкция, которая используется в bash для проверки того, является ли переменная пустой. Но тут не хватает кавычек (её более правильный вариант выглядел бы как
[ -z $var ]
). Это,
при работе с переменными, которые могут быть пустыми, часто
приводит к неприятностям.Рассмотрим обратное выражение
[ -n $var ]
, которое
проверяет переменную на то, что она является непустой. Та же
проблема с кавычками делает её полностью бесполезной:Входные данные | Ожидаемый результат | [ -n $var ] |
|
|
|
|
|
|
|
|
|
Причиной возникновения этих проблем является комбинация разделения слов и того факта, что открывающая квадратная скобка,
[
, это не часть синтаксической конструкции командной
оболочки, а всего лишь внешняя команда с необычным именем. Я уже об
этом
писал.Нахождение результатов работы команды
[
зависит от
количества аргументов. Значения аргументов гораздо слабее влияют на
результат. Вот упрощённая выдержка из описания
POSIX-команды test, составляя которую, я не обращал внимания на
отрицание:Количество аргументов | Действие | Типичный пример |
0 | Возврат False . |
|
1 | Возврат True , если аргумент $1 не
является пустым. |
|
2 | Применение унарного оператора $1 к
$2 . |
|
3 | Применение бинарного оператора $2 к
$1 и к $3 . |
|
Если это учесть становится понятным то, почему команда
[ -n
$var ]
в двух случаях ведёт себя неправильно:- Когда переменная является пустой и при этом не заключена в
кавычки, она удаляется, и мы передаём команде 1 аргумент
литеральную строку
-n
. Так как-n
не является пустой строкой команда выдаётTrue
, а должна была бы выдатьFalse
. - Когда переменная содержит
foo bar
и не заключена в кавычки, она разделяется на два аргумента, в результате мы передаём команде 3 аргумента:-n
,foo
иbar
. Так какfoo
это не бинарный оператор, результатом работы команды являетсяFalse
(с выдачей сообщения об ошибке), а, на самом деле, результатом должно бытьTrue
.
А теперь посмотрим на то, как работает
[ -z $var
]
:Входные данные | Ожидаемый результат | [ -z $var ] | Команда test |
|
True : пустая переменная |
|
1 аргумент: проверка того, является ли -z непустой
переменной |
|
False : непустая переменная |
|
2 аргумента: применение -z к foo |
|
False : непустая переменная |
False (ошибка) |
3 аргумента: применение foo к -z и
bar |
Эта команда выполняет совершенно неправильные и неожиданные действия, обрабатывая пустые строки и те случаи, которые расцениваются как передача нескольких аргументов. Но в обоих случаях ошибки приводят к получению правильных результатов.
Другими словами,
[ -z $var ]
работает гораздо лучше,
чем этого можно ожидать.Конечно, это не значит, что я призываю всех отказаться от кавычек. Для
foo bar
[ -z $var ]
вернёт правильный
код выхода, но при этом выведет некрасивое сообщение об ошибке. Для
(это строка, в которой имеются только пробелы) вернёт
True
, хотя должна вернуть False
, так как
соответствующий аргумент удаляется так, как если бы он был пустым.
Bash, кроме того, что неправильно, при попытке воспользоваться
механизмом внедрения кода, пропустит конструкцию var="foo -o
x"
, так как она будет нормально воспринята командой
test
.Какова мораль сей басни? Она такая же, как и всегда: не забывайте о кавычках. Даже тогда, когда кажется, что и без них всё работает как надо.
Утилита ShellCheck знает об этих особенностях. Тут можно проверить код, о котором мы говорили. А именно, анализируя конструкцию
[ -n $var ]
, программа разразится гневным
сообщением красного цвета, а рассматривая конструкцию [ -z
$var ]
всего лишь покажет обычное зелёное предупреждение об
отсутствии кавычек.Сталкивались ли, при работе в bash, с проблемами, связанными с кавычками?