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


10

我最近了解了watch,但是在使其使用相对复杂的命令时遇到了麻烦。

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

Answers:


16

一般提示:如果有两个嵌套级别,请避免在内部命令中使用单引号,而在外部命令周围使用单引号。

附加提示:不要使用反引号-- `…` 执行代码,而要在代码$(…)周围使用。对于嵌套的报价,美元括号几乎是DWIM(“按我的意思做”)。反引号具有不可思议的,依赖于外壳的规则。

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"'

(甚至还有更多报价!)。


谢谢@吉尔斯。那很有帮助。有趣watch-x-c,我的机器上没有nor 选项。我在网上进行了查询,但没有找到任何提及它们的手册页。这些选项有什么作用?
阿梅利奥·瓦兹克斯·雷纳

1
@intrpc -x告诉watch不要通过外壳传递命令。我只是发现这是Debian / Ubuntu特有的,即使没有这样指出。将-c被传递给zsh,不是watch
吉尔(Gilles)'所以

@Gilles -x-exec选项都存在于我的watch(在gentoo上),因此这绝对不是特定于Debian的。也许您将其与的其他版本进行了比较watch?我的来自procps软件包。
rozcietrzewiacz

1
@rozcietrzewiacz也watch来自procpsDebian。在官方消息没有--exec。Debian中的软件包(以及包括Ubuntu在内的衍生版本)在Debian特定的补丁中添加了该选项(watch_exec_beep.patch它是bug#410967的“ Mortys watch exec补丁” )。Gentoo可能已经采用了类似的补丁。
吉尔斯(Gilles)'所以
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.