我希望此命令每 2 秒在屏幕上打印一个随机值,但它不会打印任何内容:
watch bash -c '"echo $RANDOM"'
但是,此命令确实每 2 秒打印一个随机值:
watch bash -c '"echo \$RANDOM"'
显然我必须转义美元符号,但我想了解原因,因为在第一种情况下,watch 命令在顶部报告正在正确执行命令:
Every 2.0s: bash -c "echo $RANDOM"
在第二种情况下,它报告正在执行此命令,如预期的那样:
Every 2.0s: bash -c "echo \$RANDOM"
好的,我明白了,必须转义美元符号才能正确到达 bash 命令。但是,为什么?watch 命令在执行命令之前对 $RANDOM 做了什么以使其不输出任何内容?
就像评论中提到的@steeldriver 一样,默认情况
watch
下通过sh -c
. 不过,它似乎首先使用空格加入任何参数。和
它获取 args
bash
,-c
,"echo $RANDOM"
, 产生bash -c "echo $RANDOM"
, 并sh
使用两个 args-c
和bash -c "echo $RANDOM"
.然后
sh
是双引号内的变量并适当地扩展它。如果您sh
不支持 special$RANDOM
,则可能未设置整个变量,并且您在那里得到一个空字符串。然后生成的命令是bash -c "echo "
,它启动 Bash,告诉它只打印一个换行符。(如果你
sh
是 Bash 并且确实有$RANDOM
,那么你可以只使用watch 'echo $RANDOM'
。)如果添加反斜杠,外壳 (
sh
) 会看到... "echo \$RANDOM"
,它不会扩展,而只是删除反斜杠。内壳 (bash
) 看到echo $RANDOM
并扩展变量本身。如果您将外壳安排为 get... 'echo $RANDOM'
,则使用单引号也是如此。您可以看到中间外壳使用以下内容进行的扩展(它应该打印
out
):使用
watch -x
,它会跳过中间的 shell,这将按照您期望的方式工作,而无需引用地狱:从手册页:
如果你执行
echo $RANDOM
usingsh
而不是bash
你将不会得到任何输出,因为$RANDOM
在 中可用bash
,但在 中不可用sh
。