是否可以for
在watch
命令中使用 -loop ?
我不太确定如何通过我的尝试来解决此错误:
$ for i in 1 2 3; do echo $i; done
1
2
3
$ watch -n 10 for i in 1 2 3; do echo $i; done
-bash: syntax error near unexpected token `do'
$ watch for i in 1 2 3; do echo $i; done
-bash: syntax error near unexpected token `do'
$
答案1
watch
的命令参数是使用 运行的脚本sh -c
。
如果命令参数只是一个由空格分隔的标记列表(例如watch ls -l
),它将它们全部连接起来并运行它们。但未加引号的 shell 元字符是watch
由您运行的 shell 使用并且是从未见过watch
。
这意味着需要转义或引用等元字符,;
&
|
<
>
以防止您运行的 shell 将watch
这些字符视为标记命令结束watch
、在后台运行 watch 命令或通过管道传输输出的指令进入watch
另一个程序(而不是在监视脚本内运行管道)。
应用通常的引用规则 - 使用单引号来防止变量插值,否则使用双引号。 man watch
最后有一个示例部分显示了这一点。
例如:
watch -n 10 'for i in 1 2 3; do echo $i; done'
或者
watch -n 10 'grep something /var/log/kern.log | tail'
注意:如果你想在watch
没有.例如。-x
sh -c
watch -x awk -f script.awk
答案2
您键入的命令在 shell 尝试运行之前就已由当前 shell 进行了解析watch
。 shell 解释了;
,do
因为您没有采取任何措施来保护这些内容免受 shell 的影响。do
出乎意料,但首先您不希望 shell 将其解释;
为命令终止符。
一般来说,您可以通过转义(例如\;
)或引用(例如';'
)来保护事物不被 shell 解释/扩展。就您而言,您需要保护;
和$
。但接下来有一个问题:该怎么watch
办?
通常watch
不只是运行命令。它运行 shell 代码,即将一些代码传递给sh -c
.该代码是根据一个或多个参数编写的watch
(因此例如watch echo foo
工作方式类似于watch "echo foo"
)。
可以watch -x
在没有 shell 的情况下运行命令,但是要运行for
循环,您确实需要 shell。
事实上,watch
当多个空格很重要并且您不小心引用时,从多个参数构建 shell 代码可能会导致错误。另一个执行类似操作的命令是ssh
,您可以在中找到一些分析我的这个答案。
解决所有这些问题的一种方法是使用单引号一切你想成为 shell 代码,所以watch
得到正好一个包含代码的参数。在你的情况下:
watch -n 10 'for i in 1 2 3; do echo $i; done'
请注意,一般来说,代码watch
运行时sh
需要自己的引号,有时需要单引号那里,因此简单地用新的单引号包含整个代码可能会也可能不会。如果在当前 shell 的上下文中新的单引号与已存在的单引号配对,而不是彼此配对,则它将不起作用(或者在最好的情况下它会偶然起作用)。请参见如何在 Bash 中方便地使用单引号或转义整个命令行?。链接的问题包含通用手动解决方案;我的回答提供了一种在 Bash 中自动进行此类引用的方法。