Являются ли двойные квадратные скобки ] предпочтительными в квадратных скобках в Bash?

Сотрудник недавно заявил в обзоре кода, что конструкция [[ ]] предпочтительнее [ ] в конструкциях типа

 if [ "`id -nu`" = "$someuser" ] ; then echo "I love you madly, $someuser" fi 

Он не мог объяснить. Есть ли это?

7 Solutions collect form web for “Являются ли двойные квадратные скобки ] предпочтительными в квадратных скобках в Bash?”

[[ имеет меньше сюрпризов и, как правило, безопаснее использовать. Но он не переносимый – POSIX не указывает, что он делает, и поддерживают его только некоторые оболочки (кроме bash, я слышал, что ksh поддерживает его). Например, вы можете сделать

 [[ -e $b ]] 

чтобы проверить, существует ли файл. Но с [ , вы должны цитировать $b , потому что он разделяет аргумент и расширяет такие вещи, как "a*" (где [[ принимает это буквально). Это также связано с тем, как [ может быть внешней программой и получает свой аргумент как обычно, как и любая другая программа (хотя она также может быть встроенной, но тогда она еще не имеет этой специальной обработки).

[[ также имеет некоторые другие приятные функции, такие как регулярное выражение, сопоставимое с =~ наряду с операторами, как они известны на языках C-типа. Вот хорошая страница об этом: В чем разница между тестом, [ и [[ ? и тесты Bash

[[ ]] имеет больше возможностей – я предлагаю вам взглянуть на Руководство по разработке сценариев Advanced Bash для получения дополнительной информации, в частности, в разделе расширенной тестовой команды в главе 7. Тесты .

Кстати, в качестве путеводителей [[ ]] был введен в ksh88 (версия версии Korn 1988 года).

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

Во-первых, давайте проанализируем различия в поведении между ними. Протестировано в Bash 4.3.11.

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

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

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

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

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

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

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

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

      Существуют также дополнительные различия, такие как = и =~ .

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

  • <

    • [[ a < b ]] : лексикографическое сравнение
    • [ a \< b ] : То же, что и выше. \ required или выполняет redirect, как и для любой другой команды. Расширение Bash.
    • Я не мог найти альтернативу POSIX, см.: Как тестировать строки меньше или равно?
  • && и ||

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

    • [[ (a = a || a = b) && a = b ]] : false
    • [ ( a = a ) ] : синтаксическая ошибка, () интерпретируется как подshell
    • [ \( a = a -oa = b \) -aa = b ] : равнозначно, но () устарел POSIX
    • ([ a = a ] || [ a = b ]) && [ a = b ] Рекомендация POSIX
  • расщепление слов

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

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

    • [[ ab =~ ab? ]] [[ ab =~ ab? ]] : true, соответствие регулярному выражению POSIX ,? не расширяется glob
    • [ a =~ a ] : синтаксическая ошибка
    • printf 'ab' | grep -Eq 'ab?' : Эквивалент POSIX

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

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

Есть эквиваленты POSIX для каждой конструкции [[ ]] которую я видел.

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

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

С какого компаратора, теста, кронштейна или двойного кронштейна быстрее всего? ( http://bashcurescancer.com )

Двойная скобка – это «составная команда», где в качестве теста и единственной скобки используются встроенные оболочки (и на самом деле это одна и та же команда). Таким образом, одиночная скобка и двойная скобка выполняют разный код.

Тест и одиночная скобка являются наиболее переносимыми, поскольку они существуют как отдельные и внешние команды. Однако, если вы используете любую удаленно современную версию BASH, поддерживается двойная скобка.

Типичная ситуация, когда вы не можете использовать [[находится в скрипте autotools configure.ac, там скобки имеют особое и другое значение, поэтому вам придется использовать test вместо [или [[- Обратите внимание, что тест и [одинаковые программа.

[[]] двойные скобки не поддерживаются при определенной версии SunOS и полностью неавторизованных внутренних деклараций функций: GNU bash, версия 2.02.0 (1) -release (sparc-sun-solaris2.6)

В двух словах, [[лучше, потому что он не развивает другой процесс. Никакие скобки или одна скобка не медленнее, чем двойная скобка, потому что она вилки другого процесса.

  • C # - использование ключевого слова virtual + override vs. new
  • Многострочные строки в JSON
  • VBA: Различия в двух способах объявления нового объекта? (Попытка понять, почему мое решение работает)
  • Как вы печатаете unsigned long long int (спецификатор формата для unsigned long long int)?
  • Когда требуется ключевое слово «typename»?
  • Что означает двойное подчеркивание (__const) в C?
  • Как работает цикл for, особенно для (;;)?
  • Каково значение знака вопроса в MySQL в столбце WHERE =??
  • Список синтаксиса объявлений блока
  • Что означает синтаксис '=>' в C #?
  • Как выбрать все листовые узлы с помощью выражения XPath?
  • Давайте будем гением компьютера.