如何使用“watch”命令将多个也带有引号(“)的命令括起来?

如何使用“watch”命令将多个也带有引号(“)的命令括起来?

我想使用watch以下命令链的命令:

journalctl | grep 'UFW BLOCK' | grep 'DST=192.168.0.2' | awk '{printf "%-4s%-3s%-10s%-1s%+16s\n", $1, $2, $3, $7, $11, $18, $19}'

通常,当我想应用于watch命令链时,我会将命令链括在引号之间

watch "COMMAND_1 | COMMAND_2 | ... | COMMAND_n"

但是当像上面这样的命令之一中有另一个引号时,就会出错。这个问题的解决方法是什么?

答案1

为了避免担心引号,您可以使用此处的文档:

shell_code=$(cat << 'EOF'
  journalctl |
    awk '
      /UFW BLOCK/ && index($0, "DST=192.168.0.2 ") {
         printf "%-4s%-3s%-10s%-1s%+16s\n", $1, $2, $3, $7, $11, $18, $19
      }'
EOF
)

watch "$shell_code"

(或者,watch sh -c "$shell_code"如果您的watch实现尚未启动 shell 来解释命令行,而是运行命令本身,尽管这些watch实现现在越来越少了)。

其他一些注意事项:

  • awk可以做大部分grep可以做的事情,所以你很少需要将它们连接在一起。

  • .是匹配任何单个字符的正则表达式运算符。grep 192.168.0.2将匹配于192.168.012.您可以使用[.]or\.对其进行转义,或者-F使用 ingrepindex()inawk进行子字符串搜索,而不是使用正则表达式匹配。

  • 如果您不在搜索字符串中添加额外的空格,您还会找到DST=192.168.0.2例如DST=192.168.0.234。使用grep -Fw DST=192.168.0.2将解决这两个问题。

  • 我会避免使用双引号来括起 shell 代码,因为很容易忘记转义$s 或`s 并引入命令注入漏洞(变量的内容可能被解释为 shell 代码)。单引号更安全,因为可以保证其中没有特殊字符。由于这包括's 本身(至少在类似 Bourne 的 shell 中),这意味着您不能'在 中包含 s '...',但您始终可以将它们输入为'foo'\''bar',它'foo'\''用反斜杠引用)连接'bar'。所以在这里:

    watch 'journalctl |
       awk '\''
         /UFW BLOCK/ && index($0, "DST=192.168.0.2 ") {
            printf "%-4s%-3s%-10s%-1s%+16s\n", $1, $2, $3, $7, $11, $18, $19
         }'\'
    
  • journalctl有一个-f/--follow模式,新日志条目到达时会显示它们。您可能想使用它,而不是一遍又一遍地搜索完整日志。


1运行watch的实现解释其参数与空格串联的代码,但可以直接使用/选项运行命令,从而使您可以更轻松地让其他语言解释器(如或 )解释代码。procps-ngsh-x--execwatch -x zsh -c 'zsh code'watch -x perl -e 'perl code'

² 不过为了完整性,如果启用该选项,zsh(类似 Bourne;虽然也具有 rc 和 csh 的功能)可以'foo''bar'在单引号字符串中包含单引号。rcrcquotes

相关内容