Почему эта условная проверка bash работает с [[ -n ... ]], но не [ -n ... ]? [duplicate]

Я могу попробовать:

 cat infile | sed 's/,/\],\[/g
 s/ /,/g
 s/^/\[/
 s/$/\]/' > outfile
9
23.03.2018, 12:58
2 ответа

это потому, что [[] принимает выражение, а [ принимает аргументы, которые преобразует в выражение.

[[ синтаксис - это не встроенная команда, как [, а скорее [[ является составной командой и больше похож на { или (, чем на [.

в любом случае, поскольку [[ разбирается вместе с $expansions, ему нетрудно понять разницу между расширением с нулевым значением и отсутствующим операндом.

[, однако, это процедура, выполняемая после того, как все расширения командной строки уже произошли, и к тому времени, когда она оценивает свои выражения, $null_expansion уже был расширен в ничто, и поэтому все, что она получает, это [ -n ], который может не быть правильным выражением. [ согласно спецификации возвращает true для случая не-нулевого единственного аргумента - как это происходит для -n здесь - но та же самая спецификация говорит далее...

Две команды:

 test "$1"
 test ! "$1"

не могут быть надежно использованы на некоторых исторических системах. Неожиданные результаты могли бы возникнуть, если бы использовалось такое строковое выражение и $1 расширилось до ! , ( или известного унарного первичного (например, -n). Лучше использовать следующие конструкции:

 test -n "$1"
 test -z "$1" 

в обеих формах есть свои плюсы и минусы. [] выражения могут быть построены из расширений, и поэтому:

[ "-${z:-n}" "$var" ]

... может быть совершенно правильным способом построения теста, но не может быть сделано с помощью:

[[ "-${z:-n}" "$var" ]]

..., которая является бессмысленной командой. Различия полностью обусловлены точкой разбора командной строки, в которой выполняется тест.

17
27.01.2020, 20:04

Переменные не обязательно заключать в двойные кавычки в [[ ]], но они должны быть заключены в кавычки для [ ].

Без кавычек, если $value - пустая строка, то [ -n $value ] - это то же самое, что [ "-n" ]. "-n" является строковым тестом и оценивается как непустая, а значит истинная, поэтому тест проходит успешно.

(почему? потому что -n STRING и STRING одинаковы для [ aka test - они оба являются тестом на string-is-not-empty)

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

С кавычками, [ -n "$value" ] точно такое же, как [ -n "" ], поэтому тест не проходит.

[[ ... ]] гораздо более щадяще относится к цитированию переменных - цитирование необязательно, и тест работает одинаково как с кавычками, так и без них.

9
27.01.2020, 20:04

Теги

Похожие вопросы