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


Я просто задавался вопросом, что именно разница между

[[ $STRING != foo ]]

а также

[ $STRING != foo ]

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


326
2017-08-09 21:11


Источник


stackoverflow.com/questions/13542832 - Ciro Santilli 新疆改造中心 六四事件 法轮功
В случае, если вам также интересно, не использовать ли какие-либо скобки вообще, например. в контексте if утверждение, см. mywiki.wooledge.org/BashPitfalls#if_.5Bgrep_foo_myfile.5D - Kev
Кроме того, из документов Ubuntu: wiki.ubuntu.com/... - radistao


Ответы:


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

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

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

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

250
2017-08-09 21:56



Спасибо, ссылка на FAQ FAQ была тем, что я искал (не знал об этой странице, спасибо). - 0x89
Я отредактировал ваше сообщение с этой информацией, но [и тест выполняется как встроенные. Встроенные модули были созданы для замены / bin / [и / bin / test, но для воспроизведения ограничений двоичных файлов тоже были необходимы. Команда 'type [' проверяет, что используется встроенный. 'который [' ищет только исполняемые файлы в PATH и эквивалентен 'type -P [' - klynch


Вкратце:

[] - bash Встроенные команды

[[]] являются bash Ключевые слова

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

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

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

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


104
2017-12-29 19:42



[ - команда оболочки POSIX; его не нужно строить. ] это просто аргумент, который ищет эта команда, так что синтаксис сбалансирован. Команда является синонимом test Кроме этого test не ищет закрытие ], - Kaz
Глянь сюда: pubs.opengroup.org/onlinepubs/009695399/utilities/test.html - Kaz


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

Протестировано в Bash 4.3.11:

  • Расширение POSIX vs Bash:

    • [  это POSIX
    • [[ является расширением Bash
  • регулярная команда против магии

    • [ просто регулярная команда со странным именем.

      ] это просто аргумент [ что предотвращает использование дополнительных аргументов.

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

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

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

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

      Существуют и другие различия, такие как: = а также =~,

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

  • <

  • && а также ||

    • [[ a = a && b = b ]]: истинные, логические и
    • [ a = a && b = b ]: ошибка синтаксиса, && анализируется как разделитель команды И cmd1 && 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
  • расщепление слов

    • x='a b'; [[ $x = 'a b' ]]: true, котировки не нужны
    • x='a b'; [ $x = 'a b' ]: синтаксическая ошибка, расширяется до [ a b = 'a b' ]
    • x='a b'; [ "$x" = 'a b' ]: эквивалент
  • =

    • [[ ab = a? ]]: true, потому что он сопоставление образцов (* ? [ магия). Не расширяет glob для файлов в текущем каталоге.
    • [ ab = a? ]: a? glob расширяется. Так может быть истинным или ложным в зависимости от файлов в текущем каталоге.
    • [ ab = a\? ]: false, а не расширение glob
    • = а также == одинаковы для обоих [ а также [[, но == является расширением Bash.
    • printf 'ab' | grep -Eq 'a.': Эквивалент POSIX ERE
    • [[ ab =~ 'ab?' ]]: false, теряет магию ''
    • [[ ab? =~ 'ab?' ]]: правда
  • =~

Рекомендация

Я предпочитаю всегда использовать [],

Существуют эквиваленты POSIX для каждого [[ ]] конструкции, которую я видел.

Если вы используете [[ ]] вы:

  • потерять переносимость
  • заставить читателя изучить тонкости другого расширения bash. [это просто регулярная команда со странным именем, никакая специальная семантика не задействована.

59
2017-07-12 10:22



Как использовать printf 'ab' | grep -Eq 'ab?' в if [ … ]? - meeDamian
@meeDamian if ( printf 'ab' | grep -Eq 'a' ); then echo 'a'; fi, [] это команда, как grep, () может не понадобиться для этой команды. Я не уверен: я добавил ее из-за |, зависит от того, как Bash разбирает вещи. Если бы не было | Я уверен, что вы можете написать if cmd arg arg; then, - Ciro Santilli 新疆改造中心 六四事件 法轮功
@meeDamian да, нет необходимости () кажется: stackoverflow.com/questions/8965509/... - Ciro Santilli 新疆改造中心 六四事件 法轮功
Хороший список! Смотрите также: wiki.ubuntu.com/... - radistao


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


4
2017-08-09 21:17





Одиночная скобка то есть [] является оболочкой POSIX, соответствующей заключению условного выражения.

Двойные скобки то есть [[]] представляет собой расширенную (или расширенную) версию стандартной версии 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

3
2018-02-08 03:15