it-swarm-ru.tech

В чем разница между двойными и одинарными квадратными скобками в bash?

Мне просто интересно, какая именно разница между

[[ $STRING != foo ]]

а также

[ $STRING != foo ]

кроме того, что последний является posix-совместимым, встречается в sh, а первый является расширением, найденным в bash.

451
0x89

Есть несколько отличий. На мой взгляд, некоторые из наиболее важных являются:

  1. [ является встроенным в Bash и многих других современных оболочках. Встроенный [ похож на test с дополнительным требованием закрытия ]. Встроенные [ и ​​test имитируют функциональность /bin/[ а также /bin/test вместе с их ограничениями, чтобы скрипты были обратно совместимы. Оригинальные исполняемые файлы все еще существуют в основном для соответствия POSIX и обратной совместимости. Выполнение команды type [ в Bash означает, что [ по умолчанию интерпретируется как встроенный. (Запись: which [ ищет только исполняемые файлы по пути [~ # ~] [~ # ~] и эквивалентно type -p [)
  2. [[ не так совместимо, оно не обязательно будет работать с любым /bin/sh указывает на. Так [[ является более современной опцией Bash/Zsh/Ksh.
  3. Потому что [[ встроен в оболочку и не имеет устаревших требований, вам не нужно беспокоиться о разбиении Word на основе [~ # ~] ifs [~ # ~] переменная, чтобы связываться с переменными, которые оцениваются в строку с пробелами. Следовательно, вам не нужно помещать переменную в двойные кавычки.

По большей части, остальное - просто более приятный синтаксис. Чтобы увидеть больше различий, я рекомендую эту ссылку на ответ FAQ: В чем разница между test, [и [[? . На самом деле, если вы серьезно) о сценариях bash я рекомендую прочитать все wiki , включая FAQ, Pitfalls и Guide. раздел теста из раздела guide объясняет эти различия, а также, почему автор (ы) думают [[ будет лучшим выбором, если вам не нужно беспокоиться о своей портативности. Основными причинами являются:

  1. Вам не нужно беспокоиться о цитировании левой части теста, чтобы он действительно читался как переменная.
  2. Вам не нужно убегать меньше и больше, чем < > с обратными слешами, чтобы они не оценивались как перенаправление ввода, что может привести к путанице при перезаписи файлов. Это снова восходит к [[ будучи встроенным. Если [(test) - внешняя программа, Shell должна была бы сделать исключение в способе оценки < а также > только если /bin/test называется, что не имеет смысла.
325
Kyle Brandt

Короче говоря:

[это bash Встроенный

[[]] ключевые слова bash

Ключевые слова: Ключевые слова очень похожи на встроенные, но основное отличие заключается в том, что к ним применяются специальные правила синтаксического анализа. Например, [встроена в bash, а [[является ключевым словом bash. Они оба используются для тестирования, но, поскольку [[является ключевым словом, а не встроенным, оно имеет несколько специальных правил синтаксического анализа, которые делают его намного проще:

  $ [ a < b ]
 -bash: b: No such file or directory
  $ [[ a < b ]]

Первый пример возвращает ошибку, потому что bash пытается перенаправить файл b в команду [a]. Второй пример на самом деле делает то, что вы ожидаете. Символ <больше не имеет специального значения оператора перенаправления файлов.

Источник: http://mywiki.wooledge.org/BashGuide/CommandsAndArguments

138
abhiomkar

Различия в поведении

Некоторые отличия в Bash 4.3.11:

  • Расширение POSIX против Bash:

  • обычная команда против магии

    • [ - это обычная команда со странным именем.

      ] - это просто аргумент [, который не позволяет использовать дополнительные аргументы.

      Ubuntu 16.04 на самом деле имеет исполняемый файл для него по адресу /usr/bin/[, предоставляемый coreutils, но встроенная версия bash имеет преимущество.

      Ничто не изменяется в том, как Bash анализирует команду.

      В частности, < - это перенаправление, && и || объединяют несколько команд, ( ) генерирует субоболочки, если не выполняется \, а расширение Word происходит как обычно.

    • [[ X ]] - это одиночная конструкция, которая позволяет магически анализировать X. <, &&, || и () обрабатываются специально, и правила разбиения Word отличаются.

      Есть и другие отличия, такие как = и =~.

      В Bashese: [ - это встроенная команда, а [[ - ключевое слово: https://askubuntu.com/questions/445749/whats-the-difference-between-Shell-builtin-and-Shell-keyword

  • <

  • && и ||

    • [[ a = a && b = b ]]: истина, логика и
    • [ a = a && b = b ]: синтаксическая ошибка, && анализируется как разделитель команд AND cmd1 && cmd2
    • [ a = a -a b = b ]: эквивалентно, но не поддерживается POSIX³
    • [ a = a ] && [ b = b ]: POSIX и надежный эквивалент
  • (

    • [[ (a = a || a = b) && a = b ]]: false
    • [ ( 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' ]]: true, кавычки не нужны
    • 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?' ]]: false4, теряет магию с ''
    • [[ ab? =~ 'ab?' ]]: true
  • =~

    • [[ 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 Shell

², но не для некоторых значений a или b (например, + или index) и выполняет числовое сравнение, если a и ​​b выглядят как десятичные целые числа. expr "x$a" '<' "x$b" работает вокруг обоих.

³, а также завершается ошибкой для некоторых значений a или b, таких как ! или (.

4 в bash 3.2 и выше и при условии, что совместимость с bash 3.1 не включена (как с BASH_COMPAT=3.1)

5 хотя группировка (здесь с командой группой {...;} вместо (...) который должен пройти ненужную подоболочку) не является необходимым, как || и && операторы Shell (в отличие от || и && операторов [[...]] или -o/-a[ операторы) имеет равный старшинство. Так что [ a = a ] || [ a = b ] && [ a = b ] будет эквивалентен.

одна скобка т.е. [] соответствует POSIX Shell для включения условного выражения.

двойные скобки т.е. [[]] является улучшенной (или расширенной) версией стандартной версии POSIX, это поддерживается bash и другими оболочками (zsh, ksh).

В bash для числового сравнения мы используем eq, ne, lt и ​​gt, с двойными скобками для сравнения мы можем использовать ==, !=, <, а также > буквально.

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

например:

[ var1 lt var2] #works
[ var1 < var2] #error: var2 No such file or directory 
[ var1 \< var2] #works with escape
[[ var1 < var2]] #works
6
Premraj

Основываясь на быстром чтении соответствующих разделов справочной страницы, основное различие заключается в том, что == а также != операторы сопоставляются с шаблоном, а не с литеральной строкой, а также с наличием =~ оператор сравнения регулярных выражений.

4
womble