我希望此命令每 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 做了什么,使其不输出任何内容?
答案1
就像评论中提到的 @steeldriver 一样,默认情况watch
下通过 运行命令sh -c
。不过,它似乎首先用空格连接它得到的任何参数。
和
watch bash -c '"echo $RANDOM"'
它获取 args bash
、-c
、"echo $RANDOM"
、 产生bash -c "echo $RANDOM"
,并sh
使用两个 args-c
和运行bash -c "echo $RANDOM"
。
然后是sh
双引号内的变量并适当扩展它。如果您sh
不支持特殊的$RANDOM
,则整个变量可能未设置,并且您会得到一个空字符串。然后生成的命令是bash -c "echo "
,它启动 Bash,告诉它只打印换行符。
(如果您sh
是 Bash 并且确实有$RANDOM
,那么您可以直接使用watch 'echo $RANDOM'
。)
如果添加反斜杠,那里的外壳 ( sh
) 会看到... "echo \$RANDOM"
,它不会扩展,只是删除反斜杠。内壳 ( bash
) 看到echo $RANDOM
并扩展变量本身。如果您将外壳安排为 get ... 'echo $RANDOM'
,则相同,并带有单引号。
您可以看到中间 shell 使用如下内容进行的扩展(它应该打印out
):
export foo=out; watch 'bash -c "foo=in; echo $foo"'
使用watch -x
,它会跳过介入的 shell,并且这将以您期望的方式工作,而无需引用地狱:
watch -x bash -c 'echo $RANDOM'
答案2
来自手册页:
请注意,命令被赋予“sh -c”...
如果您执行echo $RANDOM
usingsh
而不是,bash
您将不会得到任何输出,因为$RANDOM
可以在 中使用bash
,但不能在 中使用sh
。