如果您已经关注 unix.stackexchange.com 一段时间了,那么您现在应该知道,echo $var在 Bourne/POSIX shell(zsh 是例外)中的列表上下文(如)中不加引号的变量具有非常特殊的含义,并且除非你有很好的理由,否则不应该这样做。
在这里的许多问答中详细讨论了它(例如:为什么我的 shell 脚本会因空格或其他特殊字符而窒息?,何时需要双引号?,shell 变量的扩展以及 glob 和 split 对其的影响,引用vs 不带引号的字符串扩展)
自从 70 年代末 Bourne shell 首次发布以来就是这种情况,并且没有被 Korn shell 改变(David Korn 最大的遗憾之一(问题 #7))或者bash大部分复制了 Korn shell,这就是POSIX/Unix 是如何指定的。
现在,我们仍然在这里看到许多答案,甚至偶尔会公开发布未引用变量的 shell 代码。你会认为人们现在已经学会了。
根据我的经验,主要有 3 类人会省略引用他们的变量:
初学者。这些可以被原谅,因为它是一种完全不直观的语法。我们在这个网站上的职责是教育他们。
健忘的人。
即使经过反复锤击也不相信的人,他们认为Bourne shell 的作者肯定没有打算让我们引用所有变量。
如果我们揭露与此类行为相关的风险,也许我们可以说服他们。
如果您忘记引用变量,那么最糟糕的事情是什么。真的有那么糟糕吗?
我们在这里谈论什么样的漏洞?
在什么情况下会出现问题?
$ ls -l /tmp/test/my\ dir/
total 0
Run Code Online (Sandbox Code Playgroud)
我想知道为什么以下运行上述命令的方法失败或成功?
$ abc='ls -l "/tmp/test/my dir"'
$ $abc
ls: cannot access '"/tmp/test/my': No such file or directory
ls: cannot access 'dir"': No such file or directory
$ "$abc"
bash: ls -l "/tmp/test/my dir": No such file or directory
$ bash -c $abc
'my dir'
$ bash -c "$abc"
total 0
$ eval $abc
total 0
$ eval "$abc"
total 0
Run Code Online (Sandbox Code Playgroud) 我可以安全地省略本地作业右侧的引号吗?
function foo {
local myvar=${bar}
stuff()
}
Run Code Online (Sandbox Code Playgroud)
我主要对 感兴趣bash,但欢迎提供有关其他 shell 中的边角案例的任何信息。
我有一个在 Linux 上运行的脚本,它接受一些参数。
我想做类似的事情:
if [[ $CONDITION == "true" ]]; then
script param1 --param2
else
script param1
fi
Run Code Online (Sandbox Code Playgroud)
我想避免if的分叉路径。
有没有更优化的方法来传递第二个参数?
我正在探索使用set -x( set +xto unset) in跟踪命令bash:
在展开之后和执行之前,打印简单命令的踪迹,用于命令、case 命令、选择命令和命令及其参数的算术或关联的单词列表。PS4 变量的值被扩展,结果值打印在命令及其扩展参数之前。
现在考虑以下内容,跟踪echo \[-neE\] \[arg …\]带和不带引号的 bash 内置命令的使用:
# set -x # what I typed
# echo 'love' # ...
+ echo love <--(1) the trace
love # the output
# echo love? # note the input contains no quote whatsoever
+ echo 'love?' <--(2) note the trace contains quotes after returning word
love? # i.e. failed to find any file
# echo 'love?' …Run Code Online (Sandbox Code Playgroud) 我正在以下列方式调用具有多个标志的 bash 脚本:
/home/username/myscript -a -b 76
Run Code Online (Sandbox Code Playgroud)
因此,为了说明,-a 标志在 myscript 中执行某些操作,而 -b 标志在 myscript 中将某些参数设置为 76。
如何根据某些先前定义的变量使这些标志成为条件?例如,如果某个变量 var=ON,我只想使用 -a 标志,否则我不知道使用该标志的内容。我正在寻找类似的东西:
var=ON
/home/username/myscript
if [ "$var" == "ON" ]; then
-a
fi
-b 76
Run Code Online (Sandbox Code Playgroud)
然而,这个方案在实施时不起作用。什么可以用来实现预期的结果?
bash ×5
quoting ×4
shell-script ×4
shell ×3
assignment ×1
scripting ×1
security ×1
trace ×1
variable ×1