我最近了解到手表,但在使用相对复杂的命令使其工作时遇到了困难。
例如,我想要求每三秒watch
运行一次以下命令*:zsh
for x in `command_1 | grep keyword | cut -d' ' -f1`; do command_2 "word[word=number]" $x; done
正如您所看到的,上面的行包含单引号、双引号以及其他特殊字符。
所以我尝试:
watch -n 3 "for x in `my_command | grep keyword | cut -d' ' -f1`; do command2 "rusage[mem=7000]" $x; done"
但后来我得到:
在 !@#$# .... 中未找到 x 的匹配项完毕
我尝试了其他组合但没有成功。这是这些尝试之一:
watch -n 3 "for x in $(bjobs -w | grep pre_seg | cut -d' ' -f1); do bmod -R "rusage[mem=7000]" $x; done"
这也会导致类似的错误。
有什么想法可以让这项工作发挥作用吗?
*我也对适用的解决方案感兴趣bash
答案1
一般提示:如果有两层嵌套,请避免在内部命令中使用单引号,并在外部命令周围使用单引号。
附加提示:不要使用反引号 - `…`
- 来执行代码,而是使用$(…)
它周围。当涉及到嵌套引号时,美元括号几乎就是 DWIM(“按照我的意思做”);反引号具有神秘的、依赖于 shell 的规则。
watch -n 3 'for x in $(my_command | grep keyword | cut -d" " -f1); do command2 "rusage[mem=7000]" "$x"; done'
如果您需要在单引号命令中使用单引号,则可以使用'\''
.将这四个字符视为在单引号内引用单引号的方式,尽管从技术上讲,这是构造为结束单引号字符串,附加文字单引号,并开始一个新的单引号字符串(仍然附加到当前词)。
对于更复杂的情况,要么仔细计算引号,要么定义临时变量。
cmd='for x in $(my_command | grep keyword | cut -d" " -f1); do command2 "rusage[mem=7000]" "$x"; done'
watch_cmd='watch -n 3 "$cmd"'
这个答案并不特定于 zsh。 Zsh 在这里没有带来任何重要的东西。您可以节省一些引用,因为命令替换不需要双引号,有时可以使用内置命令而不是外部命令来减少引用需求,但根本问题与其他 shell 相同。
哦,顺便说一句,请注意,它将watch
在 中执行您的命令sh
,而不是在 zsh 中。如果想在zsh中执行命令,需要运行
watch -n 3 -x zsh -c "$cmd"
在 Debian/Ubuntu 上,以及
export cmd
watch -n 3 'exec zsh -c "$cmd"'
(甚至更多地引用!)其他地方。