Я можу писати
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 та в усіх попередніх POSIX sh, про які я чув . (POSIX ref: прості команди ). З цієї ж причини 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, це не в Баш , навіть якщо неінтерактивний (якщо відповідність POSIX не відслідковуються з допомогою $POSIXLY_CORRECT
або --posix
...).
VAR=$VAR1
, мене іноді дивують local VAR=$VAR1
, які, як я пам'ятаю, працювали по-різному, принаймні в деяких оболонках. Але атм, я не можу відтворити розбіжність.
local VAR=$VAR1
це як export VAR=$VAR1
, це залежить від оболонки.
Вважайте, що подвійне цитування використовується для змінного розширення, а одноцитата використовується для сильного котирування, тобто розширення sans.
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 є безкоштовна онлайн-посилання, TLDP, Документаційний проект Linuxhttps://www.tldp.org/LDP/abs/html/parameter-substitution.html