я могу написать
VAR=$VAR1
VAR=${VAR1}
VAR="$VAR1"
VAR="${VAR1}"
конечный результат для меня все кажется примерно одинаковым. Почему я должен написать один или другой? какие-нибудь из них не переносимы / POSIX?
я могу написать
VAR=$VAR1
VAR=${VAR1}
VAR="$VAR1"
VAR="${VAR1}"
конечный результат для меня все кажется примерно одинаковым. Почему я должен написать один или другой? какие-нибудь из них не переносимы / POSIX?
Ответы:
VAR=$VAR1
это упрощенная версия VAR=${VAR1}
. Второе может сделать то, что первое не может, например, сослаться на индекс массива (не переносимый) или удалить подстроку (переносимый POSIX). См. Раздел « Дополнительная информация о переменных » руководства Bash для начинающих и расширения параметров в спецификации POSIX.
Использование кавычек вокруг переменной, как в rm -- "$VAR1"
или rm -- "${VAR}"
является хорошей идеей. Это делает содержимое переменной атомарной единицей. Если значение переменной содержит пробелы (ну, символы в $IFS
специальной переменной, пробелы по умолчанию) или символы глобинга, и вы не заключаете его в кавычки, то каждое слово рассматривается для генерации имени файла (глобирования), расширение которого дает столько аргументов, сколько вы делаешь.
$ find .
.
./*r*
./-rf
./another
./filename
./spaced filename
./another spaced filename
./another spaced filename/x
$ var='spaced filename'
# usually, 'spaced filename' would come from the output of some command and you weren't expecting it
$ rm $var
rm: cannot remove 'spaced': No such file or directory
# oops! I just ran 'rm spaced filename'
$ var='*r*'
$ rm $var
# expands to: 'rm' '-rf' '*r*' 'another spaced filename'
$ find .
.
./another
./spaced filename
./another spaced filename
$ var='another spaced filename'
$ rm -- "$var"
$ find .
.
./another
./spaced filename
По переносимости: в соответствии с разделом 2.6.2 POSIX.1-2008 , фигурные скобки являются необязательными.
var1=$var
расширение дает ошибку?
export VAR=$VAR1
. Что касается фигурных скобок, они являются необязательными (см. Четвертый абзац цитируемого вами раздела; это относится ко всем оболочкам до POSIX и POSIX).
${VAR}
и $VAR
в точности эквивалентны. Для простого расширения переменной единственная причина использования ${VAR}
- это когда синтаксический анализ в противном случае захватил бы слишком много символов в имя переменной, как в ${VAR1}_$VAR2
(что без скобок было бы эквивалентно ${VAR1_}$VAR2
). Наиболее украшенное разложение ( ${VAR:=default}
, ${VAR#prefix}
, ...) требуют брекетов.
В присваивании переменной разделение полей (то есть разделение в пустом пространстве в значении) и расширение имени пути (то есть глобализация) отключены, что VAR=$VAR1
в точности эквивалентно VAR="$VAR1"
во всех оболочках POSIX и во всех pre-POSIX sh, о которых я слышал , (Ссылка POSIX: простые команды ). По той же причине VAR=*
надежно устанавливает VAR
буквальную строку *
; конечно VAR=a b
устанавливает VAR
для a
поскольку b
отдельное слово в первую очередь. Вообще говоря, двойные кавычки не нужны, когда синтаксис оболочки ожидает одно слово, например, вcase … in
(но не в шаблоне), но даже там вам нужно быть осторожным: например, POSIX указывает, чтоцели перенаправления ( >$filename
) не требуют цитирования в сценариях, но некоторые оболочки, включая bash, требуют двойных кавычек даже в сценариях. См. Когда необходимо двойное цитирование? для более тщательного анализа.
В других случаях вам нужны двойные кавычки, в частности, export VAR="${VAR1}"
(которые можно эквивалентно записать export "VAR=${VAR1}"
) во многих оболочках (POSIX оставляет этот случай открытым). Сходство этого случая с простыми назначениями и рассеянный характер списка случаев, когда вам не нужны двойные кавычки, - вот почему я рекомендую просто использовать двойные кавычки, если вы не хотите разбивать и использовать глобальные символы.
IFS
символов, потому что я хочу быть в привычке. Единственным исключением является то, что я не цитирую значение при выполнении присваивания переменной (если не требуется, например, когда значение содержит пробел). Это делает подсветку синтаксиса редактора более полезной, когда есть подстановки команд, такие как FOO=$(BAR=$(BAZ=blah; printf %s "${BAZ}"); printf %s "${BAR}")
. Вместо того, чтобы раскрашивать все в «строковый» цвет, я получаю подсветку синтаксиса вложенного кода. Это также, почему я избегаю кавычек.
>$file
это нормально в сценариях POSIX, он не находится в bash, даже когда неинтерактивен (если только соблюдение POSIX не выполняется с помощью $POSIXLY_CORRECT
или --posix
...).
VAR=$VAR1
, меня иногда удивляет то local VAR=$VAR1
, что я помню, как по-другому работал, по крайней мере, в некоторых оболочках. Но я не могу воспроизвести расхождение.
local VAR=$VAR1
это как export VAR=$VAR1
, это зависит от оболочки.
Учтите, что двойные кавычки используются для раскрытия переменных, а одинарные кавычки используются для сильных кавычек, то есть без расширения.
this='foo'
that='bar'
these="$this"
those='$that'
for item in "$this" "$that" "$these" "$those"; do echo "$item"; done
foo
bar
foo
$that
Возможно, стоит упомянуть, что вы должны использовать цитату везде, где это возможно, по нескольким причинам, среди которых лучшими являются то, что это считается наилучшей практикой, и для удобства чтения. Кроме того, потому что Bash иногда бывает причудливым и часто из-за кажущихся нелогичными или неразумными / неожиданными способами, а цитата меняет неявные ожидания на явные, что уменьшает эту поверхность ошибки (или потенциальную вероятность появления в ней).
И хотя вполне законно не цитировать и работать в большинстве случаев, эта функциональность предоставляется для удобства и, вероятно, менее переносима. полностью формальная практика, гарантирующая отражение намерений и ожиданий, заключается в цитировании.
Теперь рассмотрим также, что конструкция "${somevar}"
используется для операций замещения. Несколько вариантов использования, таких как замена и массивы.
thisfile='foobar.txt.bak'
foo="${thisfile%.*}" # removes shortest part of value in $thisfile matching after '%' from righthand side
bar="${thisfile%%.*}" # removes longest matching
for item in "$foo" "$bar"; do echo "$item"; done
foobar.txt
foobar
foobar='Simplest, least effective, least powerful'
# ${var/find/replace_with}
foo="${foobar/least/most}" #single occurrence
bar="${foobar//least/most}" #global occurrence (all)
for item in "$foobar" "$foo" "$bar"; do echo "$item"; done
Simplest, least effective, least powerful
Simplest, most effective, least powerful
Simplest, most effective, most powerful
mkdir temp
# create files foo.txt, bar.txt, foobar.txt in temp folder
touch temp/{foo,bar,foobar}.txt
# alpha is array of output from ls
alpha=($(ls temp/*))
echo "$alpha" # temp/foo.txt
echo "${alpha}" # temp/foo.txt
echo "${alpha[@]}" # temp/bar.txt temp/foobar.txt temp/foo.txt
echo "${#alpha}" # 12 # length of first element (implicit index [0])
echo "${#alpha[@]}" # 3 # number of elements
echo "${alpha[1]}" # temp/foobar.txt # second element
echo "${#alpha[1])" # 15 # length of second element
for item in "${alpha[@]}"; do echo "$item"; done
temp/bar.txt
temp/foobar.txt
temp/foo.txt
Все это едва царапает поверхность конструкции "${var}"
замещения. Оптимальной ссылкой для сценариев оболочки Bash является онлайновая ссылка libre, TLDP Проект документации Linuxhttps://www.tldp.org/LDP/abs/html/parameter-substitution.html
ls -la
lrwxrwxrwx. 1 root root 31 Nov 17 13:13 prodhostname
lrwxrwxrwx. 1 root root 33 Nov 17 13:13 testhostname
lrwxrwxrwx. 1 root root 32 Nov 17 13:13 justname
конец тогда:
env=$1
if [ ! -f /dirname/${env}hostname ]
стоит упомянуть в качестве более четкого примера использования фигурных скобок