Я немного запутался в том, что эти операторы делают по-разному при использовании в bash (скобки, двойные скобки, круглые скобки и двойные скобки).
[[ , [ , ( , ((
Я видел, как люди используют их, если такие заявления:
if [[condition]]
if [condition]
if ((condition))
if (condition)
Ответы:
if
Заявление обычно выглядит следующим образомПредложение
then
выполняется, если код выходаcommands1
равен нулю. Если код выхода не равен нулю, тоelse
предложение выполняется.commands1
может быть простым или сложным. Он может, например, представлять собой последовательность из одного или нескольких конвейеров , разделенных одним из операторов;
,&
,&&
, или||
. Этиif
условия , приведенные ниже , являются лишь частными случаямиcommands1
:if [ condition ]
Это традиционная
test
команда оболочки . Он доступен на всех оболочках POSIX. Команда test устанавливает код выхода, иif
оператор действует соответственно. Типичные тесты - существуют ли файл или одно число равно другому.if [[ condition ]]
Это новая модернизированы вариация
test
из KSH , что колотить и ЗШ также поддержки. Этаtest
команда также устанавливает код выхода, иif
оператор действует соответственно. Среди его расширенных возможностей он может проверить, соответствует ли строка регулярному выражению.if ((condition))
Еще одно расширение ksh, которое также поддерживают bash и zsh . Это выполняет арифметику. В результате арифметики устанавливается код выхода и
if
оператор действует соответствующим образом. Он возвращает код выхода, равный нулю (true), если результат арифметического вычисления отличен от нуля. Мол[[...]]
, эта форма не POSIX и, следовательно, не переносимая.if (command)
Это запускает команду в подоболочке. Когда команда завершается, она устанавливает код выхода и
if
оператор действует соответственно.Типичная причина для использования подоболочки подобного типа заключается в том, чтобы ограничить побочные эффекты
command
приcommand
необходимости назначения переменных или других изменений в среде оболочки. Такие изменения не сохраняются после завершения подоболочки.if command
Команда выполняется, и
if
оператор действует в соответствии с кодом выхода.источник
[
на самом деле это двоичный файл, а не внутренняя команда или символ. Как правило, живет в/bin
.[
является встроенным, как естьtest
. Для совместимости доступны двоичные версии. Проверьтеhelp [
иhelp test
.$((
т.е. арифметическое расширение есть, и их легко спутать. Часто обходной путь - использовать что-то вроде[ $((2+2)) -eq 4 ]
использования арифметики в условных выражениях(…)
круглые скобки обозначают подоболочку . То, что внутри них, не является выражением, как во многих других языках. Это список команд (как и вне скобок). Эти команды выполняются в отдельном подпроцессе, поэтому любое перенаправление, присваивание и т. Д., Выполняемые внутри скобок, не влияют за пределы скобок.$(…)
- подстановка команды : в скобках есть команда, а вывод команды используется как часть командной строки (после дополнительных расширений, если подстановка не заключена в двойные кавычки, но это уже другая история ) ,{ … }
Скобки подобны скобкам в том смысле, что они группируют команды, но они влияют только на синтаксический анализ, а не на группировку. Программаx=2; { x=4; }; echo $x
печатает 4, тогда какx=2; (x=4); echo $x
печатает 2. (Также скобки, являющиеся ключевыми словами, должны быть разделены и найдены в позиции команды (отсюда и пробел после{
и;
перед}
), тогда как скобки - нет. Это просто синтаксическая причуда.)${VAR}
это расширение параметра , расширяющееся до значения переменной, с возможными дополнительными преобразованиями.ksh93
Оболочка также поддерживает${ cmd;}
как форму подстановки команд , которые не порождают подоболочку.((…))
двойные скобки окружают арифметическую инструкцию , то есть вычисление на целых числах, с синтаксисом, похожим на другие языки программирования. Этот синтаксис в основном используется для назначений и в условных выражениях. Это существует только в ksh / bash / zsh, а не в простой sh.$((…))
, которые расширяются до целочисленного значения выражения.[ … ]
одиночные скобки окружают условные выражения . Условные выражения в основном построены на операторах, таких как-n "$variable"
проверка, является ли переменная пустой, и-e "$file"
проверка, существует ли файл. Обратите внимание, что вам нужен пробел вокруг каждого оператора (например[ "$x" = "$y" ]
, нет) и пробел или символ, как[ "$x"="$y" ]
;
внутри, так и вне скобок (например[ -n "$foo" ]
, нет).[-n "$foo"]
[[ … ]]
двойные скобки - это альтернативная форма условных выражений в ksh / bash / zsh с несколькими дополнительными функциями, например, вы можете написать,[[ -L $file && -f $file ]]
чтобы проверить, является ли файл символической ссылкой на обычный файл, тогда как для одиночных скобок требуется[ -L "$file" ] && [ -f "$file" ]
. См. Почему расширение параметров с пробелами без кавычек работает в двойных скобках [[но не в одиночных скобках [? больше на эту тему.В оболочке каждая команда является условной командой: каждая команда имеет статус возврата, который равен либо 0, что указывает на успех, либо целому числу от 1 до 255 (и, возможно, больше в некоторых оболочках), указывающему на сбой. Команда
[ … ]
(или[[ … ]]
синтаксическая форма) - это конкретная команда, которая также может быть написанаtest …
и успешно выполняется, когда файл существует, или когда строка не пуста, или когда число меньше другого, и т. Д.((…))
Синтаксическая форма успешно выполняется, когда число ненулевой Вот несколько примеров условных выражений в сценарии оболочки:Проверьте,
myfile
содержит ли строкаhello
:Если
mydir
это каталог, измените его и сделайте вещи:Проверьте, есть ли файл, вызываемый
myfile
в текущем каталоге:То же самое, но в том числе висячие символические ссылки:
Проверьте, является ли значение
x
(которое предполагается числовым) не менее 2, переносимо:Проверьте, является ли значение
x
(которое предполагается числовым) не менее 2 в bash / ksh / zsh:источник
-a
вместо&&
, поэтому можно написать:,[ -L $file -a -f $file ]
что является одинаковым количеством символов в скобках без лишних[
и]
...-a
и-o
являются проблемными, потому что они могут привести к неправильным анализам, если некоторые из задействованных операндов выглядят как операторы. Вот почему я не упоминаю их: они имеют нулевое преимущество и не всегда работают. И никогда не пишите расширения переменных без кавычек без веской причины:[[ -L $file -a -f $file ]]
это хорошо, но вам нужны одиночные скобки[ -L "$file" -a -f "$file" ]
(что нормально, например, если$file
всегда начинается с/
или./
).[[ -L $file && -f $file ]]
(нет-a
с[[...]]
вариантом).Из документации bash :
Другими словами, вы должны убедиться, что все, что происходит в 'list' (например, a
cd
), не имеет никакого эффекта вне(
и)
. Единственное, что утечет, это код завершения последней команды илиset -e
первой команды, которая выдает ошибку (кроме нескольких, таких какif
,while
и т. Д.)Это расширение bash, позволяющее вам выполнять математику. Это несколько похоже на использование
expr
без всех ограниченийexpr
(таких как наличие пробелов везде, экранирование*
и т. Д.)Это предлагает расширенный тест для сравнения строк, чисел и файлов, немного похожий на
test
предложения, но более мощный.Этот звонит
test
. На самом деле, в старые времена,[
была символическая ссылка наtest
. Это работает так же, и у вас есть те же ограничения. Поскольку двоичный файл знает имя, под которым он был запущен, тестовая программа может анализировать параметры, пока не найдет параметр]
. Приколы Unix.Обратите внимание, что в случае
bash
,[
иtest
являются встроенными функциями (как упомянуто в комментарии), все же в значительной степени применяются те же ограничения.источник
test
и[
, конечно , встроенные команды в Bash, но это, вероятно , что внешний двоичный тоже существует.[
не является символической ссылкойtest
на большинство современных систем.strings /usr/bin/test
показывает, что он также имеет текст справки, поэтому я не знаю, что сказать.test
очевидно, требует, чтобы команда существовала как отдельная файловая команда, ничто в ней не говорит о том, что ее[
вариант также должен быть реализован таким образом. Например, Solaris 11 не предоставляет никакого[
исполняемого файла, но, тем не менее, полностью соответствует стандартам POSIX[
против[[
Этот ответ будет охватывать
[
против[[
подмножества вопроса.Некоторые отличия в 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², см .: https://stackoverflow.com/questions/21294867/how-to-test-strings-for-lexicographic-less-than-or-equal-in-bash/52707989#52707989&&
а также||
[[ a = a && b = b ]]
: правда, логично и[ a = a && b = b ]
: синтаксическая ошибка,&&
проанализированная как разделитель команд ANDcmd1 && 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 эквивалент 5разделение слов и генерация имени файла при расширениях (split + glob)
x='a b'; [[ $x = 'a b' ]]
: правда, цитаты не нужны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 расширяется. Так может быть true или false в зависимости от файлов в текущем каталоге.[ ab = a\? ]
: false, не глобальное расширение=
и==
одинаковы в обоих[
и[[
, но==
это расширение Bash.case ab in (a?) echo match; esac
: POSIX эквивалент[[ ab =~ 'ab?' ]]
: false 4 , теряет магию с''
[[ ab? =~ 'ab?' ]]
: правда=~
[[ 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-эквиваленты для каждой
[[ ]]
конструкции, которую я видел.Если вы используете
[[ ]]
вас:[
это обычная команда со странным именем, никакой особой семантики не требуется.¹ Вдохновленный эквивалентной
[[...]]
конструкции в оболочке Korn² но терпит неудачу для некоторых значений
a
илиb
(например,+
илиindex
) и выполняет числовое сравнение, еслиa
иb
выглядит как десятичные целые числа.expr "x$a" '<' "x$b"
работает вокруг обоих.³, а также терпит неудачу для некоторых значений
a
илиb
как!
или(
.4 в bash 3.2 и выше и при условии, что совместимость с bash 3.1 не включена (как с
BASH_COMPAT=3.1
)5 , хотя группировка (здесь с
{...;}
командой группой вместо(...)
которой будет запускать ненужную подоболочку) не является необходимой , как||
и&&
операторы оболочки (в отличие от||
и&&
[[...]]
операторов или-o
/-a
[
операторов) имеют одинаковый приоритет. Так[ a = a ] || [ a = b ] && [ a = b ]
было бы эквивалентно.источник
expr
к ответу. Термин «расширение Bash» не подразумевает, что Bash был первой оболочкой, добавившей некоторый синтаксис, изучения POSIX sh против Bash уже достаточно, чтобы свести меня с ума.man test
, попробовал ли тыman [
и потерялся. Это объяснит вариант POSIX.Некоторые примеры:
Традиционный тест:
test
и[
являются командами, как и любые другие, поэтому переменная разбивается на слова, если она не в кавычках.Тест нового стиля
[[ ... ]]
является (более новой) специальной конструкцией оболочки, которая работает немного по-другому, наиболее очевидным является то, что она не разбивает слова на переменные:Некоторая документация
[
и[[
здесь .Арифметический тест:
«Нормальные» команды:
Все вышеперечисленное действует как обычные команды и
if
может принимать любую команду:Несколько команд:
Или мы можем использовать несколько команд. Обтекание набора команд
( ... )
запускает их в подоболочке, создавая временную копию состояния оболочки (рабочий каталог, переменные). Если нам нужно временно запустить какую-то программу в другом каталоге:источник
Группировка Команд
( list )
Размещение списка команд в скобках приводит к созданию среды подоболочки, и каждая из команд в списке выполняется в этой подоболочке. Поскольку список выполняется в подоболочке, назначения переменных не остаются в силе после завершения подоболочки.{ list; }
Помещение списка команд в фигурные скобки приводит к тому, что список выполняется в текущем контексте оболочки . Никакая подоболочка не создана. Точка с запятой (или новая строка) следующий список обязателен. ИсточникУсловные конструкции
Одинарная скобка, т. Е.
[]
Для сравнения
==, !=, <,
и>
должна использоваться и для числового сравненияeq, ne,lt
иgt
должна использоваться.Расширенные скобки т.е.
[[]]
Во всех приведенных выше примерах мы использовали только одиночные скобки для заключения условного выражения, но bash допускает двойные скобки, что служит расширенной версией синтаксиса с одиночными скобками.
Для сравнения
==, !=, <,
и>
можно использовать буквально.[
это синоним тестовой команды. Даже если он встроен в оболочку, он создает новый процесс.[[
это новая улучшенная версия, которая является ключевым словом, а не программой.[[
понимаетсяKorn
иBash
.Источник
источник