Могу ли я безопасно пропустить кавычки в правой части локального задания?
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 in ksh
или sh
эмуляцией (или для того, export var="$(cmd)"
где zsh
иначе можно было бы разделить слова (не используя globbing)).В противном случае расширение переменной будет подвержено разделению слов и / или генерации имени файла, как в любом аргументе любой другой команды.
И не нужны в:
bash
ksh
(все реализации)sh
из FreeBSD 9.3 или более поздней версииsh
(с 2005 года)zsh
В zsh
, split + glob никогда не выполняется при расширении параметра, если только в sh
или ksh
эмуляция, но split (не glob) выполняется при замене команды. Начиная с версии 5.1, export
/ local
и другие команды объявления стали командами с двумя ключевыми словами / встроенными, как в других оболочках выше, что означает, что в кавычках нет необходимости, даже в sh
/ ksh
emulation и даже для подстановки команд.
Существуют особые случаи, когда цитирование необходимо даже в этих оболочках, например:
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
emulation).
(Обратите внимание, что var=value local var
не следует использовать, так как поведение зависит от оболочки).
Также обратите внимание, что использование export
с присваиванием также означает, что статус выхода cmd
in 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
... Специальные модули).