Есть несколько отличий. На мой взгляд, некоторые из наиболее важных являются:
[является встроенным в Баш и многих других современных оболочек. Встроенный [аналогичен 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 (не знал об этой странице, спасибо).
0x89
2
Я отредактировал ваш пост с этой информацией, но [и тест выполняются как встроенные. Встроенные функции были разработаны для замены / bin / [и / bin / test, но также должны были воспроизвести ограничения двоичных файлов. Команда 'type [' проверяет, используется ли встроенная функция. 'which [' только ищет исполняемые файлы в PATH и эквивалентен 'type -P ['
klynch
133
Короче говоря:
[Баш строит
[[]] Ключевые слова bash
Ключевые слова: ключевые слова очень похожи на встроенные, но главное отличие заключается в том, что к ним применяются специальные правила синтаксического анализа. Например, [встроена в bash, а [[является ключевым словом bash. Они оба используются для тестирования, но, поскольку [[является ключевым словом, а не встроенным, оно имеет несколько специальных правил синтаксического анализа, которые делают его намного проще:
$ [ a < b ]-bash: b:No such file or directory
$ [[ a < b ]]
Первый пример возвращает ошибку, потому что bash пытается перенаправить файл b в команду [a]. Второй пример на самом деле делает то, что вы ожидаете. Символ <больше не имеет специального значения оператора перенаправления файлов.
[является командой оболочки POSIX; его не нужно встраивать. ]это просто аргумент, который ищет эта команда, так что синтаксис сбалансирован. Команда является синонимом, за testисключением того, что testне ищет закрытие ].
]это просто аргумент, [который не позволяет использовать другие аргументы.
Ubuntu 16.04 на самом деле имеет исполняемый файл для него, /usr/bin/[предоставляемый coreutils, но встроенная версия bash имеет преимущество.
Ничто не изменяется в том, как Bash анализирует команду.
В частности, <происходит перенаправление &&и ||объединение нескольких команд, ( )генерируются подоболочки, если не выполняется экранирование \, и расширение слов происходит как обычно.
[[ X ]]это единственная конструкция, которая делает Xбыть проанализированным магическим образом. <, &&, ||И ()рассматриваются специально, и правила разбиения на слова различны.
awk 'BEGIN{exit !(ARGV[1] ~ ARGV[2])}' ab 'ab?': Эквивалент POSIX.
Рекомендация : всегда используйте [].
Есть POSIX-эквиваленты для каждой [[ ]]конструкции, которую я видел.
Если вы используете [[ ]]вас:
потерять мобильность
Заставьте читателя изучить тонкости другого расширения bash. [это обычная команда со странным именем, никакой особой семантики не требуется.
¹ Вдохновленный эквивалентной [[...]]конструкции в оболочке 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 [ … ]?
meeDamian
1
@meeDamian if ( printf 'ab' | grep -Eq 'a' ); then echo 'a'; fi. []это команда , так же , как grep. ()Не может быть необходимо в этой команде я не уверен: я добавил его из-за |, зависит от того, как Bash разбирает вещи. Если бы не было, |я уверен, что вы можете написать просто if cmd arg arg; then.
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Ответы:
Есть несколько отличий. На мой взгляд, некоторые из наиболее важных являются:
[
является встроенным в Баш и многих других современных оболочек. Встроенный[
аналогичен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 пытается перенаправить файл 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
, с двойными скобками для сравнения мы можем использовать==
,!=
,<,
и в>
буквальном смысле.[
это синоним тестовой команды. Даже если он встроен в оболочку, он создает новый процесс.[[
это новая улучшенная версия, которая является ключевым словом, а не программой.например:
источник
На основе быстрого чтения соответствующих разделов страницы руководства, основная разница , как представляется , что
==
и!=
операторы матч против шаблона, а не символьная строка, а также , что это=~
оператор сравнения регулярных выражений.источник