...

воскресенье, 30 мая 2021 г.

[Перевод] О неоправданно хорошей работе [ -z $var ]

Есть такой сабреддит — /r/nononoyes, где публикуют видео, в которых происходит что-то такое, что, на первый взгляд, кажется ужасно неправильным, идущим к катастрофе. Но в конце всё, чудесным образом, заканчивается хорошо.

В том сабреддите хорошо смотрелась бы команда [ -z $var ].


Это — конструкция, которая используется в bash для проверки того, является ли переменная пустой. Но тут не хватает кавычек (её более правильный вариант выглядел бы как [ -z «$var» ]). Это, при работе с переменными, которые могут быть пустыми, часто приводит к неприятностям.

Рассмотрим обратное выражение — [ -n $var ], которое проверяет переменную на то, что она является непустой. Та же проблема с кавычками делает её полностью бесполезной:


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

Нахождение результатов работы команды [ зависит от количества аргументов. Значения аргументов гораздо слабее влияют на результат. Вот упрощённая выдержка из описания POSIX-команды test, составляя которую, я не обращал внимания на отрицание:


Если это учесть — становится понятным то, почему команда [ -n $var ] в двух случаях ведёт себя неправильно:
  • Когда переменная является пустой и при этом не заключена в кавычки, она удаляется, и мы передаём команде 1 аргумент — литеральную строку -n. Так как -n не является пустой строкой — команда выдаёт True, а должна была бы выдать False.
  • Когда переменная содержит foo bar и не заключена в кавычки, она разделяется на два аргумента, в результате мы передаём команде 3 аргумента: -n, foo и bar. Так как foo — это не бинарный оператор, результатом работы команды является False (с выдачей сообщения об ошибке), а, на самом деле, результатом должно быть True.

А теперь посмотрим на то, как работает [ -z $var ]:
Эта команда выполняет совершенно неправильные и неожиданные действия, обрабатывая пустые строки и те случаи, которые расцениваются как передача нескольких аргументов. Но в обоих случаях ошибки приводят к получению правильных результатов.

Другими словами, [ -z $var ] работает гораздо лучше, чем этого можно ожидать.

Конечно, это не значит, что я призываю всех отказаться от кавычек. Для “foo bar” [ -z $var ] вернёт правильный код выхода, но при этом выведет некрасивое сообщение об ошибке. Для ” ” (это — строка, в которой имеются только пробелы) вернёт True, хотя должна вернуть False, так как соответствующий аргумент удаляется так, как если бы он был пустым. Bash, кроме того, что неправильно, при попытке воспользоваться механизмом внедрения кода, пропустит конструкцию var="foo -o x", так как она будет нормально воспринята командой test.

Какова мораль сей басни? Она такая же, как и всегда: не забывайте о кавычках. Даже тогда, когда кажется, что и без них всё работает как надо.

Утилита ShellCheck знает об этих особенностях. Тут можно проверить код, о котором мы говорили. А именно, анализируя конструкцию [ -n $var ], программа разразится гневным сообщением красного цвета, а рассматривая конструкцию [ -z $var ] — всего лишь покажет обычное зелёное предупреждение об отсутствии кавычек.

Сталкивались ли, при работе в bash, с проблемами, связанными с кавычками?


Adblock test (Why?)

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

Отправить комментарий