Shell 当我们需要引用或取消引用时的脚本

Shell script when we need to quote or unquote

我想了解在什么情况下我们应该在解析输出时使用引用命令,或者什么时候不应该使用。

案例 1:

我在我的 bash 脚本中使用下面的命令,它在使用下面的命令时效果很好,结果是正确的输出。

$ ssh -i /home/apache.ssh/sshKey root@dbhost01 -o StrictHostKeyChecking=no -o PasswordAuthentication=no cat /etc/redhat-release| awk 'END{print }'
6.7

案例 2:

"cat /etc/redhat-release| awk 'END{print }'" 这样的包装会导致完整的文件输出并跳过解析。

$ ssh -i /home/apache.ssh/sshKey root@dbhost01 -o StrictHostKeyChecking=no -o PasswordAuthentication=no "cat /etc/redhat-release| awk 'END{print }'"
Red Hat Enterprise Linux Server release 6.7 (Santiago)

请告知将其用于 bash 脚本时什么是正确的方法。

正确引用某事并不总是只是在开头放一个引号,在最后放一个引号。如果字符串包含在该类型引号中具有特殊含义的字符,您需要对它们进行转义或以其他方式禁用该特殊含义。

在这种情况下,造成麻烦的是 $(在 print 中)。在 double-quotes 中,$ 启动参数、命令等替换,因此 shell 将 </code> 替换为当前 shell 的第七个参数的值,并且没有,所以您将 <code>... | awk 'END{print }' 作为发送到远程计算机的命令传递给 ssh。请注意,虽然 $ 也在 single-quotes 中,但它们在 double-quotes 中,因此会被忽略(直到它们到达远程 shell,即)。

但是第 1 种情况也存在一些混淆,这种情况有效。因为命令字符串没有被引用,并且包含|,本地shell将它解析为管道中的两个单独的命令:

    ssh -i /home/apache.ssh/sshKey root@dbhost01 -o StrictHostKeyChecking=no -o PasswordAuthentication=no cat /etc/redhat-release
piped into:
    awk 'END{print }'

...因此 ssh 命令实际上获取并打印了 /etc/redhat-release 的全部内容,然后 本地 通过管道传输到 awk 并且第七个字段被拆分并打印出来。

故事的寓意:通过 ssh 发送的命令被解析(并且 quotes/escapes 被应用和删除)两次,一次在本地系统上并且第二次在远程系统上。了解哪些内容将在本地解析和应用,哪些内容将在远程解析和应用,这一点很重要。这里没有简单的规则,您真的只需要考虑您希望在本地发生什么以及您希望在远程系统上发生什么,并确保您使用的 quoting/escaping 能够实现。