Подтвердить что ты не робот

Тест на пустую строку с X ""

Я знаю, что могу проверить пустую строку в Bash с помощью -z следующим образом:

if [[ -z $myvar ]]; then do_stuff; fi

но я вижу много кода, написанного как:

if [[ X"" = X"$myvar" ]]; then do_stuff; fi

Является ли этот метод более переносимым? Является ли это просто историческим крушением до дней -z? Это для оболочек POSIX (хотя я видел, что он использовался в таргетинге на сценарии bash)? Готов к моему уроку истории/переносимости.


Тот же вопрос задавался на сервере Fault как Как определить, является ли переменная Bash пустой?, но никто не предложил объяснения, почему вы видите код с материалом X"".

4b9b3361

Ответ 1

В принципе, поскольку в те времена, когда давно прошло, поведение test было более сложным и неравномерно определенным в разных системах (поэтому переносимый код должен был быть написан тщательно, чтобы избежать не переносных конструкций).

В частности, перед тем, как test был встроенным оболочкой, он был отдельным исполняемым файлом (и обратите внимание, что в MacOS X все еще есть /bin/test и /bin/[ в качестве исполняемых файлов). Когда это было так, напишите:

if [ -z $variable ]

когда $variable был пустым, вызывал бы тестовую программу через свой псевдоним [ с тремя аргументами:

argv[0] = "["
argv[1] = "-z"
argv[2] = "]"

потому что переменная была пустой, поэтому нечего было расширять. Таким образом, безопасный способ написания кода:

if [ -z "$variable" ]

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

Другая проблема, разрешенная префиксом X, - это то, что произошло, если переменные включают в себя ведущие тире или содержат равные или другие компараторы. Рассмотрим (не совсем хороший пример):

x="-z"
if [ $x -eq 0 ]

Является ли это пустым строковым тестом с ошибочным (ошибочным) аргументом или методом числового равенства с нечисловым первым аргументом? Различные системы предоставляли разные ответы до того, как POSIX стандартизировала поведение примерно в 1990 году. Таким образом, безопасный способ борьбы с этим был:

if [ "X$x" = "X0" ]

или (менее обычно, по моему опыту, но полностью эквивалентно):

if [ X"$x" = X"0" ]

Это были все краевые случаи, подобные этому, связанный с возможностью того, что тест был отдельным исполняемым файлом, а это означает, что переносимый код оболочки по-прежнему использует двойные кавычки более обильно, чем на самом деле требуют современные оболочки, а нотация X-prefix был использован для обеспечения того, чтобы вещи не могли быть истолкованы неверно.

Ответ 2

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

Мне также нравится это, потому что этот трюк почти наследуется от прошлого, самых старых вычислений, и вы сталкиваетесь с ним, когда пытаетесь прочитать некоторые из самых переносимых сценариев оболочки там (autoconf, configure и т.д. )