Различия в поведении
Некоторые отличия в Bash 4.3.11:
Расширение POSIX против Bash:
обычная команда против магии
[
это обычная команда со странным именем.
]
это просто аргумент, [
который не позволяет использовать другие аргументы.
Ubuntu 16.04 на самом деле имеет исполняемый файл для него, /usr/bin/[
предоставляемый coreutils , но встроенная версия bash имеет преимущество.
Ничто не изменяется в том, как Bash анализирует команду.
В частности, <
происходит перенаправление &&
и ||
объединение нескольких команд, ( )
генерируются подоболочки, если не выполняется экранирование \
, и расширение слов происходит как обычно.
[[ X ]]
это единственная конструкция, которая делает X
быть разобранным магическим образом. <
, &&
, ||
И ()
рассматриваются специально, и правила разбиения на слова различны.
Есть и другие отличия, как =
и =~
.
В Bashese: [
это встроенная команда и [[
ключевое слово: /ubuntu/445749/whats-the-difference-between-shell-builtin-and-shell-keyword
<
&&
а также ||
[[ 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 эквивалент⁵
разделение слов и генерация имени файла при расширениях (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⁴, теряет магию с ''
[[ 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-эквиваленты для каждой [[ ]]
конструкции, которую я видел.
Если вы используете [[ ]]
вас:
- потерять мобильность
- Заставьте читателя изучить тонкости другого расширения bash.
[
это обычная команда со странным именем, никакой особой семантики не требуется.
¹ Вдохновленный эквивалентной [[...]]
конструкции в оболочке Korn
² но терпит неудачу для некоторых значений a
или b
(например, +
или index
) и выполняет числовое сравнение, если a
и b
выглядит как десятичные целые числа. expr "x$a" '<' "x$b"
работает вокруг обоих.
³, а также терпит неудачу для некоторых значений a
или b
как !
или (
.
⁴ в bash 3.2 и выше и при условии, что совместимость с bash 3.1 не включена (как с BASH_COMPAT=3.1
)
⁵ хотя группировка (здесь с {...;}
командой группой вместо (...)
которой будет работать ненужную подоболочку) не является необходимым , как ||
и &&
оболочками операторов (в отличие от ||
и &&
[[...]]
операторов или -o
/ -a
[
операторов) имеет одинаковый приоритет. Так [ a = a ] || [ a = b ] && [ a = b ]
было бы эквивалентно.
[[
с ним код хорошо и понятно, но помните тот день , когда вы будете порт ваших scriptworks по системе с оболочкой по умолчанию , который не являетсяbash
илиksh
, и т. д.[
уродливее, громоздче, но работает какAK-47
в любой ситуации.