![局部变量赋值需要引号吗?](https://linux22.com/image/3219/%E5%B1%80%E9%83%A8%E5%8F%98%E9%87%8F%E8%B5%8B%E5%80%BC%E9%9C%80%E8%A6%81%E5%BC%95%E5%8F%B7%E5%90%97%EF%BC%9F.png)
我可以安全地省略本地作业右侧的引号吗?
function foo {
local myvar=${bar}
stuff()
}
我主要对 感兴趣bash
,但欢迎任何有关其他 shell 中的极端情况的信息。
答案1
export foo="$var"
or local foo="$var"
(或readonly
, typeset
,declare
以及其他变量声明中需要引号命令) 在:
dash
版本 0.3.8-15 至 0.5.10.2(请参阅改变)。- NetBSD的
sh
(也基于 Almquist shell)。 sh
FreeBSD 9.2 或更早版本的(请参阅9.3 中的变化)yash
zsh
5.1 之前的版本在ksh
或sh
仿真中(或在export var="$(cmd)"
何处zsh
执行分词,否则(不是通配符))。
否则,变量扩展将受到分词和/或文件名生成的影响,就像任何其他命令的任何参数一样。
并且在以下情况下不需要:
bash
ksh
(所有实现)- FreeBSD
sh
9.3 或更新版本 - busybox' 基于 ash
sh
(自 2005 年起) zsh
dash
0.5.11 或更高版本。
在 中zsh
,split+glob 永远不会在参数扩展时完成,除非在sh
或ksh
仿真中,但 split(不是 glob)是在命令替换时完成的。从5.1版本开始,export
/local
和其他声明命令变成了双重的关键词/内置像上面其他 shell 中的命令一样,这意味着不需要引用,即使在sh
/ksh
模拟中,甚至对于命令替换也是如此。
在某些特殊情况下,即使在这些 shell 中也需要引用,例如:
a="b=some value"
export "$a"
=
或者更一般地说,如果(包括)的剩余部分=
被引用或某些扩展的结果(例如export 'foo'="$var"
, export foo\="$var"
or export foo$((n+=1))="$var"
($((...))
实际上也应该被引用)...)。或者换句话说,export
如果在没有export
.
如果export
/local
命令名称本身被引号引起来(即使部分像"export" a="$b"
、'ex'port a="$b"
、\export a="$b"
、 甚至""export a="$b"
),则需要引号,$b
除了 AT&Tksh
和mksh
最新版本的dash
.
如果export
/或它的某些部分是某些扩展的结果(例如 in或 Even )或类似)local
的结果,则需要引号,但在最新版本的.cmd=export; "$cmd" a="$b"
export$(:) a="$b"
dryrun=; $dryrun export a="$b"
dash
在 的情况下> /dev/null export a="$b"
,需要pdksh
及其一些衍生品的报价。
对于command export a="$b"
,每个 shell 中都需要引号,但mksh
、ksh93
、最近的dash
和 除外(对于和不是除 之外的 shell 中某些扩展的结果,也有bash -o posix
相同的警告)。command
export
dash
编写时,任何 shell 中都不需要它们:
foo=$var export foo
(该语法也与 Bourne shell 兼容,但在最新版本的 中zsh
,仅在sh
/ksh
模拟中有效)。
(请注意,var=value local var
不应使用它,因为不同 shell 的行为有所不同)。
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
我的建议是总是引用。
答案2
我通常会引用可能存在空格等字符的变量的任何用法。否则你会遇到这样的问题:
#!/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
我们使用它时的内容。