В сценарии оболочки, если я определяю переменную, такую как 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нигде.
$в конце концов! Он будет обрабатываться как обычный символ, а не как часть имени переменной.