Предпочтительнее ли двойные квадратные скобки []] над одиночными квадратными скобками [] в Bash?
сотрудник заявил недавно в обзоре кода, что [[ ]]
конструкция должна быть предпочтительнее [ ]
в конструкции типа
if [ "`id -nu`" = "$someuser" ] ; then
echo "I love you madly, $someuser"
fi
он не мог дать разумного объяснения. Есть такой?
7 ответов
[[
меньше сюрпризов и, как правило, безопаснее использовать. Но это не портативный-POSIX не указывает, что он делает, и только некоторые оболочки поддерживают его (рядом с bash, я слышал, что ksh тоже поддерживает его). Например, вы можете сделать
[[ -e $b ]]
чтобы проверить, существует ли файл. Но с [
, вы должны цитировать $b
, потому что он разбивает аргумент и расширяет такие вещи, как "a*"
(где [[
занимает она в буквальном смысле). Это также связано с тем, как [
может быть внешним программа и получает свой аргумент так же нормально, как и любая другая программа (хотя она также может быть встроенной, но тогда она все еще не имеет этой специальной обработки).
[[
также имеет некоторые другие приятные функции, такие как регулярное выражение, соответствующее =~
вместе с операторами, как они известны в C-подобных языках. Вот хорошая страница об этом:в чем разница между тестом,[
и [[
? и Bash Тесты
[[ ]]
больше возможностей - я предлагаю вам взглянуть на Расширенный Bash Руководство Сценариев для получения дополнительной информации, в частности расширенный вариант команды test на Глава 7. Тесты.
кстати, как отмечает руководство, [[ ]]
был представлен в ksh88 (версия 1988 оболочки Korn).
различия в поведении
во-первых, давайте проанализируем различия в поведении обоих. Испытано в Bash 4.3.11.
-
расширение POSIX vs Bash:
-
[
это POSIX -
[[
является расширением Bash
-
-
обычная команда против магии
-
[
- Это просто обычная команда со странным имя.]
- это просто аргумент[
Это предотвращает использование дополнительных аргументов.Ubuntu 16.04 на самом деле имеет исполняемый файл для него в
/usr/bin/[
предоставлено coreutils, но встроенная версия bash имеет приоритет.ничего не изменяется в том, как Bash анализирует команду.
в частности,
<
перенаправление,&&
и||
объединить несколько команд( )
генерирует подэлементы, если не экранирован by\
, и расширение слова происходит, как обычно. -
[[ X ]]
- это одна конструкция, которая делаетX
волшебно разбирается.<
,&&
,||
и()
обрабатываются специально, и правила разделения слов различны.есть также дополнительные различия, такие как
=
и=~
.
В Bashese:
[
является встроенной командой, и[[
- ключевое слово: https://askubuntu.com/questions/445749/whats-the-difference-between-shell-builtin-and-shell-keyword -
-
<
-
[[ a < b ]]
: лексикографическое сравнение -
[ a \< b ]
: то же, что и выше.\
требуется или делает перенаправление, как для любой другой команды. Расширение Баш. - я не мог найти альтернативу POSIX для этого, см.:Как проверить строки меньше или равны?
-
-
&&
и||
-
[[ 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 ]]
: false -
[ ( a = a ) ]
: синтаксическая ошибка,()
интерпретируется как subshell -
[ \( a = a -o a = b \) -a a = b ]
: эквивалент, но()
устарел POSIX -
([ a = a ] || [ a = b ]) && [ a = b ]
рекомендация POSIX
-
-
разбиение
-
x='a b'; [[ $x = 'a b' ]]
: правда, кавычки не нужны -
x='a b'; [ $x = 'a b' ]
: синтаксическая ошибка, расширяется до[ a b = 'a b' ]
-
x='a b'; [ "$x" = 'a b' ]
: эквивалент
-
-
=
-
[[ ab = a? ]]
: верно, потому что это шаблоны (* ? [
волшебные). Не glob расширяется до файлов в текущем каталоге. -
[ ab = a? ]
:a?
Глоб расширяется. Так может быть true или false в зависимости от файлов в текущем каталоге. -
[ ab = a\? ]
: false, не расширение glob -
=
и==
одинаковы в обоих[
и[[
, а==
является расширением Bash. -
printf 'ab' | grep -Eq 'a.'
: POSIX ERE эквивалент -
[[ ab =~ 'ab?' ]]
: false, теряет магию с''
-
[[ ab? =~ 'ab?' ]]
: правда
-
-
=~
-
[[ ab =~ ab? ]]
: верно, POSIX расширенное регулярное выражение матч?
не Глоб расширить -
[ a =~ a ]
: синтаксическая ошибка -
printf 'ab' | grep -Eq 'ab?'
: в POSIX эквивалент
-
рекомендация
я предпочитаю всегда использовать []
.
существуют эквиваленты POSIX для каждого [[ ]]
конструкцию я видел.
если вы используете [[ ]]
вы:
- потерять мобильность
- заставьте читателя изучить тонкости другого расширения bash.
[
- Это обычная команда со странным именем, без специальной семантики вовлеченный.
с который компаратор, тест, кронштейн, или двойной кронштейн, самый быстрый? (http://bashcurescancer.com)
двойной кронштейн представляет собой " соединение команда " где как тест и одиночный кронштейн встроенные раковины (и внутри действительность - та же команда). Таким образом, одиночный кронштейн и двойной кронштейн выполнить другой код.
тест и одиночный кронштейн большинство портативных как они существуют как отдельный и внешняя команда. Однако, если вы используете любой удаленно современная версия BASH, the double кронштейн поддержан.
типичная ситуация, когда вы не можете использовать [[ в Autotools configure.AC script, там скобки имеют особое и другое значение, поэтому вам придется использовать test
вместо [ или [[ -- обратите внимание, что test и [- одна и та же программа.
[[ ]] двойные скобки не указаны в определенной версии SunOS и полностью не указаны в объявлениях функций : GNU bash, версия 2.02.0 (1)-release (sparc-sun-solaris2.6)
в двух словах, [[лучше, потому что это не вилка другого процесса. Никакие кронштейны или один кронштейн не медленнее, чем двойной кронштейн, потому что он развивает другой процесс.