Чи можу я безпечно опустити цитати в правій частині місцевого завдання?
function foo {
local myvar=${bar}
stuff()
}
Мене в основному цікавить bash
, але будь-яка інформація про кутові корпуси в інших оболонках вітається.
Чи можу я безпечно опустити цитати в правій частині місцевого завдання?
function foo {
local myvar=${bar}
stuff()
}
Мене в основному цікавить bash
, але будь-яка інформація про кутові корпуси в інших оболонках вітається.
Відповіді:
Котирування необхідні export foo="$var"
або local foo="$var"
(або readonly
, typeset
, declare
та інші змінні оголошенні команд ) в:
dash
sh
з NetBSD (також на основі Almquist оболонки).sh
З FreeBSD 9.2 або старше (див змін до 9.3 )yash
zsh
з версіями до 5.1 в ksh
або sh
емуляції (або для того, export var="$(cmd)"
де zsh
було б виконано розділення слів в іншому випадку (не глобулювання)).Оскільки інакше розширення змінної буде підлягати розщепленню слів та / або генерації імен файлів, як у будь-якому аргументі будь-якої іншої команди.
І вони не потрібні:
bash
ksh
(усі реалізації)sh
з FreeBSD 9.3 або більш пізньої версіїsh
(з 2005 р.)zsh
У zsh
, split + glob ніколи не робиться при розширенні параметрів, якщо тільки не відбувається sh
або ksh
емуляція, але роздвоєння (не glob) робиться після заміни команди. Оскільки версія 5.1, export
/ local
та інші команди декларації стали подвійними ключовими словами / вбудованими командами, як і в інших оболонках вище, що означає, що цитування не є необхідним, навіть в sh
/ ksh
емуляції та навіть для заміни команд.
Існують особливі випадки, коли цитування потрібно навіть у цих оболонках, хоча так:
a="b=some value"
export "$a"
Або загалом, якщо що-небудь, що залишилося від =
(включаючи =
), цитується або є результатом якогось розширення (наприклад export 'foo'="$var"
, export foo\="$var"
або export foo$((n+=1))="$var"
(що $((...))
також має бути цитується фактично) ...). Або іншими словами, коли аргумент export
не буде дійсним призначенням змінної, якщо він написаний без знака export
.
Якщо export
/ local
ім'я команди сам котируються (навіть в частині , як "export" a="$b"
, 'ex'port a="$b"
, \export a="$b"
або навіть ""export a="$b"
), лапки навколо $b
потрібні тільки в AT & T ksh
і mksh
.
Якщо export
/ local
або якась її частина є результатом деякого розширення (наприклад, у cmd=export; "$cmd" a="$b"
або навіть export$(:) a="$b"
) або в подібних речах dryrun=; $dryrun export a="$b"
), то лапки потрібні в кожній оболонці.
У випадку з > /dev/null export a="$b"
котируваннями потрібні pdksh
деякі та його похідні.
Для command export a="$b"
, лапки необхідні в будь-який оболонці , але mksh
і ksh93
(з тими ж застереженнями по приводу command
і export
не є результатом якого - то розширення).
Вони не потрібні в жодній оболонці, коли пишеться:
foo=$var export foo
(цей синтаксис також сумісний з оболонкою Bourne, але в останніх версіях zsh
, працює лише під час введення sh
/ ksh
емуляції).
(зауважте, var=value local var
його не слід використовувати, оскільки поведінка різниться в оболонках).
Також зауважте, що використання export
з призначенням також означає, що статус виходу cmd
в export var="$(cmd)"
. Зробити це так, як export var; var=$(cmd)
немає цієї проблеми.
Також остерігайтеся цього особливого випадку bash
:
$ bash -c 'IFS=; export a="$*"; echo "$a"' bash a b
ab
$ bash -c 'IFS=; export a=$*; echo "$a"' bash a b
a b
Моя порада буде завжди цитувати.
zsh
лапках будуть необхідні для local foo="$(cmd)"
тому wordsplitting (але не ім'я файлу покоління) буде виконуватися для некотируваних підстановки команд (але не для некотируваних розширень параметрів), якщо KSH_TYPESET
не включене, і в цьому випадку лапки НЕ потрібна. Мати сенс? Ні? Тоді завжди цитуйте все, якщо ви точно не знаєте, що робите.
Я загалом цитую будь-яке використання змінних, де можуть бути символи, такі як пробіли. Інакше у вас виникнуть такі проблеми:
#!/bin/bash
bar="hi bye"
function foo {
local myvar=${bar}
printf "%s\n" $myvar
printf "%s\n" "$myvar"
}
foo
Використання змінної у призначенні, як видається, не потребує лапок, але коли ви перейдете до її використання, як, наприклад, у printf
потрібному вам цитуванні:
printf "%s\n" "$myvar"
ПРИМІТКА. Пам'ятайте, що змінна $IFS
- це те, що регулює, якими є символи роздільника.
IFS The Internal Field Separator that is used for word splitting after
expansion and to split lines into words with the read builtin command.
The default value is ``<space><tab><newline>''.
Увімкнувши налагодження в Bash, ми можемо бачити, що відбувається за кадром.
$ bash -x cmd.bash
+ bar='hi bye'
+ foo
+ local 'myvar=hi bye'
+ printf '%s\n' hi bye
hi
bye
+ printf '%s\n' 'hi bye'
hi bye
У вищесказаному ми можемо побачити, що змінна $bar
була передана штрафом, $myvar
але тоді, коли ми перейшли до використання, $myvar
нам довелося визначити вміст, $myvar
коли ми перейшли до її використання.
bash
і ksh
в local
/ typeset
... Спеціальні модулі).