В сценарии оболочки, если я определяю переменную, такую как FOO=25
, есть ли разница между ссылками на нее как $FOO$
и ${FOO}$
?
В сценарии оболочки, если я определяю переменную, такую как FOO=25
, есть ли разница между ссылками на нее как $FOO$
и ${FOO}$
?
Ответы:
В большинстве ситуаций оба $var
и ${var}
одинаковы. (Обратите внимание, что вы не должны использовать $
в конце!)
Один пример, где вам нужны фигурные скобки, - это когда вам нужно поместить переменную в непрерывную строку.
Пример:
var=hel
echo ${var}lo
будет выводить hello
.
Чтобы ответить на ваш главный вопрос, ${foo}
это называется «расширение параметров» . Чтобы быть точным, $
сам запускает расширение параметров, { }
они на самом деле необязательны в соответствии со спецификацией POSIX , но могут быть полезны для указания конца имени переменной:
$ foo="bar"
$ echo $fooBaz ## fails, no variable named $fooBaz exists
$ echo ${foo}Baz ## works, $foo is expanded and the string Baz is appended
barBaz
В основном $foo
и ${foo}
идентичны. За исключением случаев, подобных описанному выше, или когда вы выполняете манипуляции со строками , они полностью эквивалентны.
Тем не менее, вы не должны использовать ни один из них. Эмпирическое правило заключается в том, что, за очень немногими исключениями, вы должны всегда использовать "$foo"
или "${foo}"
и никогда $foo
или ${foo}
. Вы всегда должны заключать в кавычки свои переменные, чтобы избежать вызова оператора split + glob (подробнее об этом позже). Вы, конечно, не хотите $foo$
. Финал не $
имеет значения:
$ foo="bar"
$ echo "$foo$"
bar$
Итак, в то время как переменные без кавычек иногда в порядке:
$ echo $foo
bar
Их обычно нет, и их действительно следует избегать:
$ if [ -n $foo ]; then echo empty; else echo "not empty"; fi ## fails
empty
$ if [ -n "$foo" ]; then echo empty; else echo "not empty"; fi ## works
not empty
Обратите внимание, что скобки здесь тоже не помогают:
$ if [ -n ${foo} ]; then echo empty; else echo "not empty"; fi ## fails
empty
$ if [ -n "${foo}" ]; then echo empty; else echo "not empty"; fi ## works
not empty
Когда вы используете $foo
или ${foo}
, оболочка разделяет значение, сохраненное в переменной на пустое пространство (это можно изменить, установив IFS
переменную в другое значение), в список, а затем каждый элемент списка обрабатывается как глобальный шаблон и разворачивается в любые соответствующие файлы или каталоги. Это известно как оператор split + glob . Для иллюстрации рассмотрим каталог с двумя файлами:
$ ls -l
-rw-r--r-- 1 terdon terdon 0 Oct 9 18:16 file1
-rw-r--r-- 1 terdon terdon 0 Oct 9 18:16 file2
Теперь давайте установим переменную в foo *
:
$ foo="foo *"
Что произойдет, если мы попытаемся проверить, существует ли файл с таким именем?
$ if [ -e $foo ]; then echo "file exists"; else echo "no such file"; fi
file exists
Переменная была разбита на foo
и *
и, поскольку *
это подстановочный знак, который соответствует любой строке, оболочка сообщает вам, что файл называется foo *
exxists. Однако, если мы процитируем это правильно, этого не произойдет:
$ if [ -e "$foo" ]; then echo "file exists"; else echo "no such file"; fi
no such file
Это был тривиальный пример, чтобы проиллюстрировать это. Представь, если бы я использовал rm
вместо этого, echo
хотя.
Итак, первое правило: всегда указывайте свои переменные. Вы можете использовать либо "$foo"
или, "${foo}"
но процитировать его в любом случае. Чтобы узнать больше о безопасном использовании переменных, взгляните на эти сообщения:
$ var="foo *"
ли $ foo="foo *"
? Вы не используете var
нигде.
$
в конце концов! Он будет обрабатываться как обычный символ, а не как часть имени переменной.