Мне просто интересно, какая именно разница между
[[ $STRING != foo ]]
а также
[ $STRING != foo ]
кроме того, что последний соответствует posix, встречается в sh, а первый является расширением, найденным в bash.
Мне просто интересно, какая именно разница между
[[ $STRING != foo ]]
а также
[ $STRING != foo ]
кроме того, что последний соответствует posix, встречается в sh, а первый является расширением, найденным в bash.
Ответы:
Есть несколько отличий. На мой взгляд, некоторые из наиболее важных являются:
[является встроенным в Баш и многих других современных оболочек. Встроенный [аналогичен testдополнительному требованию закрытия ]. Встроенные функции [и testимитируют функциональность, /bin/[а /bin/testтакже их ограничения, чтобы сценарии были обратно совместимы. Оригинальные исполняемые файлы все еще существуют в основном для соответствия POSIX и обратной совместимости. Запуск команды type [в Bash означает, что [по умолчанию она интерпретируется как встроенная. (Примечание: which [ищет только исполняемые файлы в PATH и эквивалентно type -p [)[[не так совместимо, оно не обязательно будет работать с тем, на что /bin/shуказывает. Так же [[как и более современный вариант Bash / Zsh / Ksh.[[он встроен в оболочку и не имеет устаревших требований, вам не нужно беспокоиться о разбиении слов на основе переменной IFS, чтобы связываться с переменными, которые оцениваются как строка с пробелами. Следовательно, вам не нужно помещать переменную в двойные кавычки.По большей части, остальное - просто более приятный синтаксис. Чтобы увидеть больше различий, я рекомендую эту ссылку на ответ на часто задаваемый вопрос: В чем разница между test, [и [[? , На самом деле, если вы серьезно относитесь к написанию сценариев bash, я рекомендую прочитать всю вики , включая FAQ, Pitfalls и Guide. Раздел теста из раздела руководства также объясняет эти различия, и почему авторы считают, что [[это лучший выбор, если вам не нужно беспокоиться о своей портативности. Основными причинами являются:
< >с обратными слешами, чтобы они не оценивались как перенаправление ввода, которое может действительно испортить некоторые вещи, перезаписывая файлы. Это снова восходит к тому, чтобы [[быть встроенным. Если [(test) - внешняя программа, оболочка должна будет сделать исключение в способе оценки <и >только в том случае, если она /bin/testвызывается, что на самом деле не имеет смысла.Короче говоря:
[Баш строит
[[]] Ключевые слова bash
Ключевые слова: ключевые слова очень похожи на встроенные, но главное отличие заключается в том, что к ним применяются специальные правила синтаксического анализа. Например, [встроена в bash, а [[является ключевым словом bash. Они оба используются для тестирования, но, поскольку [[является ключевым словом, а не встроенным, оно имеет несколько специальных правил синтаксического анализа, которые делают его намного проще:
$ [ a < b ]
-bash: b: No such file or directory
$ [[ a < b ]]
Первый пример возвращает ошибку, потому что bash пытается перенаправить файл b в команду [a]. Второй пример на самом деле делает то, что вы ожидаете. Символ <больше не имеет специального значения оператора перенаправления файлов.
Источник: http://mywiki.wooledge.org/BashGuide/CommandsAndArguments
[является командой оболочки POSIX; его не нужно встраивать. ]это просто аргумент, который ищет эта команда, так что синтаксис сбалансирован. Команда является синонимом, за testисключением того, что testне ищет закрытие ].
Различия в поведении
Некоторые отличия в Bash 4.3.11:
Расширение POSIX против Bash:
[ это POSIX[[расширение Bash¹, задокументированное по адресу: https://www.gnu.org/software/bash/manual/bash.html#Conditional-Constructsобычная команда против магии
[ это обычная команда со странным именем.
]это просто аргумент, [который не позволяет использовать другие аргументы.
Ubuntu 16.04 на самом деле имеет исполняемый файл для него, /usr/bin/[предоставляемый coreutils, но встроенная версия bash имеет преимущество.
Ничто не изменяется в том, как Bash анализирует команду.
В частности, <происходит перенаправление &&и ||объединение нескольких команд, ( )генерируются подоболочки, если не выполняется экранирование \, и расширение слов происходит как обычно.
[[ X ]]это единственная конструкция, которая делает Xбыть проанализированным магическим образом. <, &&, ||И ()рассматриваются специально, и правила разбиения на слова различны.
Есть и другие отличия, как =и =~.
В Bashese: [это встроенная команда и [[ключевое слово: https://askubuntu.com/questions/445749/whats-the-difference-between-shell-builtin-and-shell-keyword
<
[[ a < b ]]: лексикографическое сравнение[ a \< b ]То же, что и выше. \требуется или же делает перенаправление как для любой другой команды. Расширение Bash.expr a \< b > /dev/null: Эквивалент POSIX², см .: https://stackoverflow.com/questions/21294867/how-to-test-strings-for-lexicographic-less-than-or-equal-in-bash/52707989#52707989&& а также ||
[[ a = a && b = b ]]: правда, логично и[ a = a && b = b ]: синтаксическая ошибка, &&проанализированная как разделитель команд ANDcmd1 && cmd2 [ a = a -a b = b ]: эквивалентно, но не рекомендуется POSIX³[ a = a ] && [ b = b ]: POSIX и надежный аналог(
[[ (a = a || a = b) && a = b ]]: ложный[ ( a = a ) ]: синтаксическая ошибка, ()интерпретируется как подоболочка[ \( a = a -o a = b \) -a a = b ]: эквивалентно, но ()не поддерживается POSIX{ [ a = a ] || [ a = b ]; } && [ a = b ]POSIX эквивалент 5разделение слов и генерация имени файла при расширениях (split + glob)
x='a b'; [[ $x = 'a b' ]]: правда, цитаты не нужныx='a b'; [ $x = 'a b' ]: синтаксическая ошибка, расширяется до [ a b = 'a b' ]x='*'; [ $x = 'a b' ]: синтаксическая ошибка, если в текущем каталоге более одного файла.x='a b'; [ "$x" = 'a b' ]: POSIX эквивалент=
[[ ab = a? ]]: true, потому что он выполняет сопоставление с образцом ( * ? [это волшебство). Не расширяется до файлов в текущем каталоге.[ ab = a? ]: a?glob расширяется. Так может быть true или false в зависимости от файлов в текущем каталоге.[ ab = a\? ]: false, не глобальное расширение=и ==одинаковы в обоих [и [[, но ==это расширение Bash.case ab in (a?) echo match; esac: POSIX эквивалент[[ ab =~ 'ab?' ]]: false 4 , теряет магию с''[[ ab? =~ 'ab?' ]]: правда=~
[[ ab =~ ab? ]]: true, POSIX расширенное совпадение с регулярным выражением , ?не расширяется[ a =~ a ]: ошибка синтаксиса. Нет эквивалента Bash.printf 'ab\n' | grep -Eq 'ab?': Эквивалент POSIX (только однострочные данные)awk 'BEGIN{exit !(ARGV[1] ~ ARGV[2])}' ab 'ab?': Эквивалент POSIX.Рекомендация : всегда используйте [].
Есть POSIX-эквиваленты для каждой [[ ]]конструкции, которую я видел.
Если вы используете [[ ]]вас:
[это обычная команда со странным именем, никакой особой семантики не требуется.¹ Вдохновленный эквивалентной [[...]]конструкции в оболочке Korn
² но терпит неудачу для некоторых значений aили b(например, +или index) и выполняет числовое сравнение, если aи bвыглядит как десятичные целые числа. expr "x$a" '<' "x$b"работает вокруг обоих.
³, а также терпит неудачу для некоторых значений aили bкак !или (.
4 в bash 3.2 и выше и при условии, что совместимость с bash 3.1 не включена (как с BASH_COMPAT=3.1)
5 , хотя группировка (здесь с {...;}командой группой вместо (...)которой будет запускать ненужную подоболочку) не является необходимой , как ||и &&операторы оболочки (в отличие от ||и && [[...]]операторов или -o/ -a [операторов) имеют одинаковый приоритет. Так [ a = a ] || [ a = b ] && [ a = b ]было бы эквивалентно.
printf 'ab' | grep -Eq 'ab?'внутри if [ … ]?
if ( printf 'ab' | grep -Eq 'a' ); then echo 'a'; fi. []это команда , так же , как grep. ()Не может быть необходимо в этой команде я не уверен: я добавил его из-за |, зависит от того, как Bash разбирает вещи. Если бы не было, |я уверен, что вы можете написать просто if cmd arg arg; then.
(): stackoverflow.com/questions/8965509/…
Single Bracket ie []- это оболочка POSIX, соответствующая условному выражению.
Double Brackets ie [[]]- это расширенная (или расширенная) версия стандартной версии POSIX, это поддерживается bash и другими оболочками (zsh, ksh).
В Баше, для количественного сравнения мы используем eq, ne, ltи gt, с двойными скобками для сравнения мы можем использовать ==, !=, <,и в >буквальном смысле.
[это синоним тестовой команды. Даже если он встроен в оболочку, он создает новый процесс.[[ это новая улучшенная версия, которая является ключевым словом, а не программой. например:
[ var1 lt var2] #works
[ var1 < var2] #error: var2 No such file or directory
[ var1 \< var2] #works with escape
[[ var1 < var2]] #works
ifоператора, см. Mywiki.wooledge.org/BashPitfalls#if_.5Bgrep_foo_myfile.5D