我是 Linux shell 的初学者,但我知道这个命令会创建一个子 shell:
子 shell 通常是使用子 shell 运算符或命令(例如括号 ()、反引号 ` 或 $() 语法)创建的。
: ${FOO:=$([ "$BAR" = "baz" ] && echo "true" || echo "false" )}
这可能是一个问题,例如在循环中(这里的情况并非如此)但我喜欢学习如何避免它。一般来说,在上面的作业中,可以使用以下内容来避免子shell吗?
if [ -z "$FOO" ]; then
if [ "$BAR" = "baz" ]; then
FOO=true
else
FOO=false
fi
fi
答案1
一般来说,在上面的分配中,是否可以使用以下内容来避免子shell?
if [ -z "$FOO" ]; then if [ "$BAR" = "baz" ]; then FOO=true else FOO=false fi fi
是的,这才是正确的写法。
: ${FOO:=$([ "$BAR" = "baz" ] && echo "true" || echo "false" )}
运行子 shell(在大多数 shell 中涉及代价高昂的进程分叉),并且由于以下几个原因也是错误的:
- 该
${FOO...}
扩展未加引号,因此受到 split+glob 的影响,使其至少成为 DoS 漏洞(这是给出的示例之一)忘记在 bash/POSIX shell 中引用变量的安全隐患)。 echo "false"
[
如果或失败则运行,而您希望它仅在失败echo true
时运行。不能适当替代.[
a && b || c
if a; then b; else c; fi
在 ksh93 shell 中,可以通过以下方式避免子 shell 和这些问题:
: "${FOO:=${
if [ "$VAR" = baz ]; then
echo true
else
echo false
fi
}}"
但这与上面标准且明显的if
陈述相比没有什么优势。
答案2
对于一个神秘的单行,我认为这将在没有子 shell 的情况下达到预期的结果:
[[ "$BAR" = "baz" ]] && FOO=${FOO-true} || FOO=${FOO-false}
但我会选择if....