如何在 ssh / 远程 bash 命令中转义单引号字符?

Posted

技术标签:

【中文标题】如何在 ssh / 远程 bash 命令中转义单引号字符?【英文标题】:How to escape the single quote character in an ssh / remote bash command? 【发布时间】:2013-12-28 05:07:43 【问题描述】:

我正在构建一小组用于远程启动、停止和检查进程状态的脚本。这些脚本的stop 应该寻找一个进程并杀死它。所以我这样做:

ssh deploy@hera 'kill -9 `ps -ef | grep MapReduceNode | grep -v "grep" | awk -F " " 'print $2' | head -n 1`'

这里的问题是 awk 标记化步骤需要单引号,并且这些与用于通过 ssh 执行远程命令的单引号冲突。这些单引号怎么转义?

【问题讨论】:

尝试> ssh deploy@hera 'kill -9 `ps -ef | grep MapReduceNode | grep -v "grep" | awk -F " " "'"打印 $2"'" |头 -n 1`' @RedX 这工作谢谢!用它作为答案,我会接受。 【参考方案1】:

使用

ssh deploy@hera 'kill -9 `ps -ef | grep MapReduceNode | grep -v "grep" | awk -F " " '"'"'print $2'"'"' | head -n 1`'

解释:

ssh deploy@hera 'kill -9 `ps -ef | grep MapReduceNode | grep -v "grep" | awk -F " " '"'"'print $2'"'"' | head -n 1`'
                >                               1                                   <>2<>    3     <>4<>      5      <

1) 命令开头的第一个字符串:'kill -9 `ps -ef | grep MapReduceNode | grep -v "grep" | awk -F " " '

2) 第二个字符串只有一个 ' 字符:"'"

3) 打印命令的第三个字符串:'print $2'

4) 带有另一个单引号的第四个字符串:"'"

5) 带有命令其余部分的第五个字符串:' | head -n 1`'

【讨论】:

一个解释会比仅仅解决这个特定问题的一个班轮更好。【参考方案2】:

这不是sshawk 处理引号,而是shell(它们是防止shell 专门处理其他字符的必要条件,例如$)。不支持嵌套它们(尽管其他结构,例如 $() 即使包含引号也可能嵌套),因此您需要单独转义单引号。这里有几个方法:

$ echo 'Don'"'"'t mess with this apostrophe!'
Don't mess with this apostrophe!
$ echo 'Don'\''t mess with this apostrophe!'
Don't mess with this apostrophe!

【讨论】:

【参考方案3】:

我在其他任何答案中都没有看到另外两个选项。出于演示目的,我已将 grep/grep/awk/head 管道完好无损,即使(如 rici's answer 中提到的那样)它可能会简化为类似

awk -F ' ' '/MapReduceNod[e]/  print $2; exit '

    对整个 ssh 命令使用双引号:

     ssh deploy@hera "kill -9 \$(ps -ef |
     grep MapReduceNode | grep -v \"grep\" | awk -F ' ' 'print \$2' | head -n 1)"
    

    请注意,我现在可以在命令中使用单引号,但我必须转义其他我不想扩展的内容:\$()(我使用它而不是反引号),双引号 \",和print \$2

    带引号分隔符的 here-doc:

     ssh -T deploy@hera <<'EOF'
     kill -9 $(ps -ef | grep MapReduceNode | grep -v 'grep' |
     awk -F ' ' 'print $2' | head -n 1)
     EOF
    

    -T 防止 ssh 抱怨未分配伪终端。

    带有引号分隔符的 here-doc 非常好,因为它的内容根本不需要修改关于转义的东西,并且它可以包含单引号。

【讨论】:

here-doc 示例非常有用,因为它提醒您引用 EOF 会影响以下文本是否由 bash 评估。【参考方案4】:

您不能在单引号字符串中包含单引号。但是,这并不重要,因为单个参数可以有多个带引号的段(只要没有不带引号的空格或其他自定界字符。)

例如:

ssh deploy@hera 'kill -9 `ps -ef |
                 grep MapReduceNode |
                 grep -v "grep" |
                 awk -F " " '\''print $2'\'" |
                 head -n 1`"

但是,该命令行非常很笨拙。如果可能,您应该使用pkill 实用程序,这会将所有这些都减少到ssh deploy@hera 'pkill -SIGKILL MapReduceNode'

否则,您可以在单个 awk 调用中完成所有字符串操作(未经测试,但我认为它会起作用):

ssh deploy@hera 'ps -ef |
                 awk "/[M]apReduceNode/system(\"kill -9 \"$2)"'

(与原来的不同,这将杀死所有 MapReduceNode 任务,而不是任意的第一个任务。如果您真的只想完成一项任务,请将 ; exit 添加到 awk 操作中。)

【讨论】:

【参考方案5】:

另一个例子是处理单引号或双引号,因为例如我需要解释和变量替换。如果我想创建一个功能来向我的女人的 macOS 显示一条消息,我可以执行以下操作:

ssh womanLptp "osascript -e 'tell app \"System Events\" to display dialog \"$1\"'"

【讨论】:

以上是关于如何在 ssh / 远程 bash 命令中转义单引号字符?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 JavaScript 中转义单引号 ( ' )? [复制]

如何在 Presto 中转义单引号?

如何在 MySQL 中转义单引号

如何在 Sybase 中转义单引号

如何在jQuery变量中转义单引号

如何在单引号字符串中转义单引号