将包含单引号和双引号的命令包装到另一个命令中

将包含单引号和双引号的命令包装到另一个命令中

我最近了解到手表,但在使用相对复杂的命令使其工作时遇到了困难。

例如,我想要求每三秒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"'

(甚至更多地引用!)其他地方。

相关内容