Я читаю примеры bash, if
но некоторые примеры написаны в квадратных скобках:
if [ -f $param ]
then
#...
fi
другие с двойными квадратными скобками:
if [[ $? -ne 0 ]]
then
start looking for errors in yourlog
fi
В чем разница?
bash
if-statement
rkmax
источник
источник
Ответы:
Одиночные
[]
тесты на послеродовые условия.Double
[[]]
- это расширение стандарта[]
и поддерживается bash и другими оболочками (например, zsh, ksh). Они поддерживают дополнительные операции (а также стандартные операции posix). Например:||
вместо-o
и регулярное выражение с=~
. Более полный список различий можно найти в разделе руководства bash по условным конструкциям .Используйте
[]
всякий раз, когда вы хотите, чтобы ваш сценарий был переносимым между оболочками. Используйте,[[]]
если вы хотите, чтобы условные выражения не поддерживались[]
и не были переносимыми.источник
[[ ]]
(например, bash с#!/bin/bash
или#!/usr/bin/env bash
), вы должны использовать параметр portable. Сценарии, в которых предполагается, что / bin / sh поддерживает такие расширения, будут работать в таких ОС, как недавние выпуски Debian и Ubuntu, где это не так.Различия в поведении
Протестировано в 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:
[
это встроенная команда и[[
ключевое слово: /ubuntu/445749/whats-the-difference-between-shell-builtin-and-shell-keyword<
[[ a < b ]]
: лексикографическое сравнение[ a \< b ]
То же, что и выше.\
требуется или же делает перенаправление как для любой другой команды. Расширение Bash.expr a \< b > /dev/null
: POSIX эквивалента², см .: Как проверить строки на лексикографический меньше или равно в Bash?&&
и||
[[ 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 расширяется. Так может быть истина или ложь в зависимости от файлов в текущем каталоге.[ 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-эквиваленты для каждой
[[ ]]
конструкции, которую я видел.Если вы используете
[[ ]]
вас:[
это обычная команда со странным именем, никакой особой семантики не требуется.¹ Вдохновленный эквивалентной
[[...]]
конструкции в оболочке Корн² но терпит неудачу для некоторых значений
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 ]
было бы эквивалентно.источник
[]
следует читать как Мои предпочтения : используйте,[]
если вы не хотите терять мобильность . Как указано здесь : Если переносимость / соответствие POSIX или BourneShell является проблемой, следует использовать старый синтаксис. Если, с другой стороны, сценарию требуется BASH, Zsh или KornShell, новый синтаксис обычно более гибкий, но не обязательно обратно совместимый. Я предпочел бы пойти,[[ ab =~ ab? ]]
если я могу и не беспокоиться о обратной совместимости, чемprintf 'ab' | grep -Eq 'ab?'
Внутри одинарных скобок для проверки условий (т. Е. [...]) некоторые операторы, такие как single
=
, поддерживаются всеми оболочками, тогда как использование операторов==
не поддерживается некоторыми более старыми оболочками.Внутри двойных скобок для проверки состояния (т. Е. [[...]]) нет разницы между использованием
=
или==
в старых или новых оболочках.Изменить: Я должен также отметить, что: В bash всегда используйте двойные скобки [[...]], если это возможно, потому что это безопаснее, чем одиночные скобки. Я поясню почему на следующем примере:
если $ var оказывается пустым / пустым, то это то, что видит скрипт:
который сломает ваш сценарий. Решение состоит в том, чтобы либо использовать двойные скобки, либо всегда не забывать заключать в кавычки переменные (
"$var"
). Двойные скобки лучше защитной практики кодирования.источник
[[
это ключевое слово bash, похожее на (но более мощное, чем)[
команда.Видеть
http://mywiki.wooledge.org/BashFAQ/031 и http://mywiki.wooledge.org/BashGuide/TestsAndConditionals
Если вы не пишете для POSIX sh, мы рекомендуем
[[
.источник
Вы можете использовать двойные квадратные скобки для сопоставления легких регулярных выражений, например:
if [[ $1 =~ "foo.*bar" ]] ; then
(если версия bash, которую вы используете, поддерживает этот синтаксис)
источник
Руководство Bash говорит:
(Тестовая команда идентична [])
источник