Я запутался с использованием одинарных или двойных скобок. Посмотрите на этот код:
dir="/home/mazimi/VirtualBox VMs"
if [[ -d ${dir} ]]; then
echo "yep"
fi
Это работает отлично, хотя строка содержит пробел. Но когда я изменяю это на одну скобку:
dir="/home/mazimi/VirtualBox VMs"
if [ -d ${dir} ]; then
echo "yep"
fi
Это говорит:
./script.sh: line 5: [: /home/mazimi/VirtualBox: binary operator expected
Когда я изменяю это на:
dir="/home/mazimi/VirtualBox VMs"
if [ -d "${dir}" ]; then
echo "yep"
fi
Работает нормально. Может кто-нибудь объяснить, что происходит? Когда я должен назначать двойные кавычки вокруг переменных, "${var}"
чтобы избежать проблем, вызванных пробелами?
Ответы:
Одиночная скобка
[
- это псевдонимtest
команды, а не синтаксис.Один из недостатков (из многих) одиночной скобки заключается в том, что если один или несколько операндов пытается вычислить, возвращает пустую строку, он будет жаловаться, что ожидал двух операндов (двоичных). Вот почему вы видите, что люди делают
[ x$foo = x$blah ]
,x
гарантии того, что операнд никогда не будет оцениваться как пустая строка.Двойная скобка
[[ ]]
, с другой стороны, является синтаксисом и гораздо более способна, чем[ ]
. Как вы выяснили, у него нет проблемы с одним операндом, и он также допускает больше C-подобного синтаксиса с>, <, >=, <=, !=, ==, &&, ||
операторами.Я рекомендую следующее: если ваш переводчик
#!/bin/bash
, то всегда используйте[[ ]]
Важно отметить, что
[[ ]]
это поддерживается не всеми оболочками POSIX, однако многие оболочки поддерживают его, напримерzsh
иksh
в дополнение кbash
источник
$foo
есть!
или(
или-n
... Эта проблема не подразумевается как проблема с оболочками POSIX, где число аргументов (кроме[
и]
) не превышает четырех.[ x$foo = x$blah ]
же просто, как неправильно[ $foo = $bar ]
.[ "$foo" = "$bar" ]
корректен в любой POSIX-совместимой оболочке,[ "x$foo" = "x$bar" ]
будет работать в любой Bourne-подобной оболочке, ноx
это не для случаев, когда у вас есть пустые строки, но где$foo
может быть!
или-n
...[
это не совсем псевдоним дляtest
. Если бы это было так, тоtest
приняли бы закрывающую квадратную скобку.test -n foo ]
, Ноtest
не[
требует , а требует.[
идентиченtest
во всех других отношениях, но это не так, какalias
работает. Bash описывает[
иtest
как встроенные оболочки , но[[
как ключевое слово оболочки .>=
и<=
Команда
[
это обычная команда. Хотя большинство оболочек предоставляют его как встроенный для эффективности, он подчиняется нормальным синтаксическим правилам оболочки.[
в точности эквивалентноtest
, за исключением того, что[
требует в]
качестве последнего аргумента a иtest
не делает.Двойные скобки
[[ … ]]
имеют специальный синтаксис. Они были введены в ksh (через несколько лет[
), потому что их использование[
может быть проблематичным и[[
допускает некоторые новые приятные дополнения, которые используют специальные символы оболочки. Например, вы можете написатьпотому что все условное выражение анализируется оболочкой, тогда как
[ $x = foo && $y = bar ]
сначала будет разделено на две команды[ $x = foo
и$y = bar ]
разделены&&
оператором. Точно так же двойные скобки позволяют такие вещи, как синтаксис сопоставления с образцом, например,[[ $x == a* ]]
чтобы проверить,x
начинается ли значение сa
; в одиночных скобках это расширитa*
список файлов, имена которых начинаются сa
текущего каталога. Двойные скобки были впервые введены в ksh и доступны только в ksh, bash и zsh.Внутри одинарных скобок необходимо использовать двойные кавычки вокруг подстановок переменных, как и в большинстве других мест, потому что они являются просто аргументами команды (которая является
[
командой). Внутри двойных скобок вам не нужны двойные кавычки, потому что оболочка не разбивает и не разбивает слова: она разбирает условное выражение, а не команду.Исключением являются случаи,
[[ $var1 = "$var2" ]]
когда вам нужны кавычки, если вы хотите сделать сравнение строк в байтах, в противном случае$var2
это будет образец для$var1
сравнения.Одна вещь, которую вы не можете сделать,
[[ … ]]
это использовать переменную в качестве оператора. Например, это совершенно законно (но редко полезно):В вашем примере
команда внутри
if
есть[
с 4 -х аргументов-d
,/home/mazimi/VirtualBox
,VMs
и]
. Оболочка разбирает-d /home/mazimi/VirtualBox
и потом не знает что делатьVMs
. Вы должны были бы предотвратить разделение слов,${dir}
чтобы получить правильно сформированную команду.Вообще говоря, всегда используйте двойные кавычки вокруг подстановок переменных и команд, если только вы не знаете, что хотите выполнить разбиение слов и глобализацию результата. Основные места, где нельзя использовать двойные кавычки:
foo=$bar
(но учтите, что вам нужны двойные кавычки вexport "foo=$bar"
или в присваиваниях массива, какarray=("$a" "$b")
);case
заявленииcase $foo in …
:;=
или==
оператора (если вы не хотите делать сопоставления с образцом):[[ $x = "$y" ]]
.Во всех этих случаях правильно использовать двойные кавычки, так что вы можете также пропустить расширенные правила и использовать кавычки все время.
источник
[
действительно из Системы III в 1981 году я думал, что она старше.Подразумевается в этом вопросе
${variable_name}
не означает, что вы думаете, что это делает ...… Если вы думаете, что это как- то связано с проблемами, вызванными пробелами (в значениях переменных). хорошо для этого:
${variable_name}
и ничего больше! 1 не приносит никакой пользы, если вы сразу не следите за ним с помощью символа, который может быть частью имени переменной: буквы (-или-), подчеркивания () или цифры (-). И даже тогда вы можете обойти это:
${variable_name}
A
Z
a
z
_
0
9
Я не пытаюсь препятствовать его использованию -
echo "${bar}d"
возможно, это лучшее решение здесь, - но я не рекомендую людям полагаться на фигурные скобки вместо кавычек или инстинктивно применять фигурные скобки, а затем спрашивать: «Теперь мне тоже нужны кавычки ? « Вы всегда должны использовать кавычки, если у вас нет веских причин не делать этого, и вы уверены, что знаете, что делаете._________________
1 За исключением, конечно, того факта, что причудливые формы расширения параметров , например, и строятся на синтаксисе. Кроме того , вам нужно использовать , и т.д., чтобы ссылаться на 10 - й, 11 - й и т.д., позиционные параметры - котировки не поможет вам в этом.
${parameter:-[word]}
${parameter%[word]}
${parameter}
${10}
${11}
источник
Для обработки пробелов и пробелов | специальных символов в переменных вы всегда должны заключать их в двойные кавычки. Установка правильного IFS также является хорошей практикой.
Рекомендуется: http://www.dwheeler.com/essays/filenames-in-shell.html
источник