Сотрудник недавно заявил в обзоре кода, что конструкция [[ ]]
должна быть предпочтительнее [ ]
в конструкциях типа
if [ "`id -nu`" = "$someuser" ] ; then
echo "I love you madly, $someuser"
fi
Он не мог объяснить. Есть один?
[[
имеет меньше неожиданностей и, как правило, безопаснее использовать. Но он не переносимый - POSIX не указывает, что он делает, и поддерживают его только некоторые оболочки (помимо bash, я слышал, что ksh поддерживает его). Например, вы можете сделать
[[ -e $b ]]
проверить, существует ли файл. Но с [
вы должны процитировать $b
, потому что он разделяет аргумент и расширяет такие вещи, как "a*"
(где [[
берет его буквально). Это также связано с тем, что [
может быть внешней программой и получает свой аргумент как обычно, как и любая другая программа (хотя она также может быть встроенной, но тогда она еще не имеет этой специальной обработки).
[[
также имеет некоторые другие приятные функции, такие как регулярное выражение, соответствующее =~
, а также такие операторы, как они известны на языках C-типа. Вот хорошая страница об этом: В чем разница между тестами, [
и [[
? и Bash Тесты
Различия в поведении
Некоторые отличия в Bash 4.3.11:
Расширение POSIX против Bash:
[
это POSIX[[
является расширением Bash¹, задокументировано по адресу: https://www.gnu.org/software/bash/manual/bash.html#Conditional-Constructsобычная команда против магии
[
это обычная команда со странным именем.
]
это просто аргумент [
который не позволяет использовать дальнейшие аргументы.
Ubuntu 16.04 на самом деле имеет исполняемый файл для него в /usr/bin/[
предоставляемый coreutils, но встроенная версия bash имеет преимущество.
Ничто не изменяется в том, как Bash анализирует команду.
В частности, <
это перенаправление, &&
и ||
конкатенируя несколько команд, ( )
генерирует подоболочки, если их не экранирует \
, и расширение слов происходит как обычно.
[[ X ]]
- это единственная конструкция, которая делает магический анализ X
<
, &&
, ||
и ()
обрабатываются специально, а правила разбиения слов различны.
Есть и другие отличия, такие как =
и =~
.
В Bashese: [
является встроенной командой, а [[
является ключевым словом: https://askubuntu.com/questions/445749/whats-the-difference-between-shell-builtin-and-shell-keyword
<
[[ a < b ]]
: лексикографическое сравнение[ a \< b ]
: то же, что и выше. \
Требуется или же делает перенаправление, как для любой другой команды. Расширение Bash.expr a \< b >/dev/null
: эквивалент POSIX², см. Как проверить строки на лексикографическое значение, меньшее или равное в Bash? &&
и ||
[[ a = a && b = b ]]
: верно, логично и[ a = a && b = b ]
: синтаксическая ошибка, &&
анализируется как разделитель cmd1 && cmd2
AND 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 ]
{ [ a = a ] || [ a = b ]; } && [ a = b ]
POSIX эквивалент 5разделение слов и генерация имени файла при расширении (split + glob)
x='a b'; [[ $x = 'ab' ]]
x='a b'; [[ $x = 'ab' ]]
: правда, кавычки не нужныx='a b'; [ $x = 'ab' ]
x='a b'; [ $x = 'ab' ]
: синтаксическая ошибка, расширяется до [ ab = 'ab' ]
x='*'; [ $x = 'ab' ]
x='*'; [ $x = 'ab' ]
: синтаксическая ошибка, если в текущем каталоге более одного файла.x='a b'; [ "$x" = 'ab' ]
x='a b'; [ "$x" = 'ab' ]
: эквивалент POSIX =
[[ ab = a? ]]
[[ ab = a? ]]
: true, потому что он выполняет сопоставление с образцом (*? [
являются волшебными). Не расширяется до файлов в текущем каталоге.[ ab = a? ]
[ ab = a? ]
: a?
шар расширяется. Так может быть true или false в зависимости от файлов в текущем каталоге.[ ab = a\? ]
[ ab = a\? ]
: ложно, не глобальное расширение=
и ==
одинаковы как в [
и в [[
, но ==
является расширением Bash.case ab in (a?) echo match; esac
case ab in (a?) echo match; esac
: POSIX эквивалент[[ ab =~ 'ab?' ]]
[[ ab =~ 'ab?' ]]
: false 4 теряет магию с ''
[[ ab? =~ 'ab?' ]]
[[ ab? =~ 'ab?' ]]
: правда =~
[[ ab =~ ab? ]]
[[ ab =~ ab? ]]
: Верно, POSIX регулярное выражение матч, ?
не расширяется[ a =~ a ]
: синтаксическая ошибка. Нет эквивалента Bash.printf 'ab\n' | grep -Eq 'ab?'
: Эквивалент POSIX (только однострочные данные)awk 'BEGIN{exit !(ARGV[1] ~ ARGV[2])}' ab 'ab?'
: POSIX эквивалент. Рекомендация: всегда используйте []
.
Есть эквиваленты POSIX для каждой конструкции [[ ]]
которую я видел.
Если вы используете [[ ]]
вы:
[
это обычная команда со странным именем, никакой особой семантики не требуется. ¹ Вдохновленный эквивалентной [[...]]
конструкцией в оболочке Корна
² но терпит неудачу для некоторых значений 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 ]
[ a = a ] || [ a = b ] && [ a = b ]
будет эквивалентно.
[
по тем же причинам.
[[ ]]
имеет больше возможностей - я предлагаю вам ознакомиться с Advanced Bash Scripting Guide для получения дополнительной информации, в частности расширенная тестовая команда в Глава 7. Тесты.
Кстати, в качестве путеводителей, [[ ]]
был введен в ksh88 (версия версии Korn 1988 года).
Из Какой компаратор, тест, скобка или двойная скобка быстрее всего? (http://bashcurescancer.com)
Двойная скобка является "составной команда", где в качестве теста и сингла кронштейн - это встроенные оболочки (и в актуальность - та же самая команда). Таким образом, одиночный кронштейн и двойной кронштейн выполнить другой код.
Тест и одиночная скобка являются поскольку они существуют как отдельные и внешние команды. Однако, если вы используете удаленно современная версия BASH, двойная поддерживается кронштейн.
[[
может принести. Но тогда я старый пердун старой школы :-)
[
и test
хотя внешние версии также существуют.
Типичная ситуация, когда вы не можете использовать [[находится в autotools configure.ac script), там скобки имеют особое и другое значение, поэтому вам нужно будет использовать test
вместо [или [[- Примечание этот тест и [являются одной и той же программой.
[
быть определенным как функция оболочки POSIX?
В двух словах, [[лучше, потому что он не развивает другой процесс. Никакие скобки или одна скобка не являются более медленными, чем двойная скобка, потому что она вызывает еще один процесс.
type [
чтобы увидеть это.
[[
в отличие от [
, это синтаксис, интерпретируемый интерпретатором командной строки bash. В bash попробуйте набрать type [[
. Unix4linux правильно, что хотя классическая оболочка Bourne [
тесты запускает новый процесс для определения значения истинности, синтаксис [[
заимствован из ksh bash, zsh и т. д.) - нет.
[[]] двойные скобки не поддерживаются при определенной версии SunOS и полностью неавторизованных внутренних деклараций функций: GNU bash, версия 2.02.0 (1) -release (sparc-sun-solaris2.6)
[[
с ним, код хорош и понятен, но помните тот день, когда вы будете переносить ваши скриптовые работы в систему с оболочкой по умолчанию, которая не являетсяbash
илиksh
и т. д.[
уродлив, громоздок, но в любой ситуации работает какAK-47
.