首页 > 解决方案 > 似乎无法逃避脚本化的 bash 命令。每次错误/不正确的输出

问题描述

好吧,这要死我了。我知道我必须转义双引号等,但是我无法让下面的脚本化 bash 命令正常工作。

在远程服务器上,以下命令按预期工作:

sed 's|EX_ROOT=/root/$SERVER|EX_ROOT="/root/$SERVER"|g'  /etc/example/config.conf

结果:EX_ROOT="/root/$SERVER"

(这是预期的)

但是,当从不同的服务器远程运行命令时,如下所示:

ssh root@$HWNODEIP "sed 's|EX_ROOT=/root/$SERVER|EX_ROOT="/root/$SERVER"|g' /etc/example/config.conf"

不添加双引号。所以我记得我必须转义双引号。但在这里我遇到了一堵墙。无论我尝试什么,我都没有得到预期的结果。

示例 1:

ssh root@$HWNODEIP "sed 's|EX_ROOT=/root/$SERVER|EX_ROOT="\""/root/$SERVER"\""|g' /etc/example/config.conf"

给出:EX_ROOT="/root/"$SERVER

($SERVER 不在引号内)

示例 2:

ssh root@$HWNODEIP "sed 's|EX_ROOT=/root/$SERVER|EX_ROOT=\"/root/\$SERVER\"|g' /etc/example/config.conf"

给出:EX_ROOT="/root/$SERVER"$SERVER

(关闭但仍然不是预期的结果)

预期/期望的结果:

EX_ROOT="/root/$SERVER"

我不知道我在这里做错了什么。我知道我很接近,但真的不知道。我尝试了其他一些事情,例如使用更多引号并试图逃避更多,但都没有结果,现在我没有想法......

标签: bashescaping

解决方案


您的第一次尝试不会向远程服务器发送双引号;他们在本地关闭并重新打开您的双引号字符串。

你需要逃离他们。您的示例 2 是close,但您忘记在正则表达式中转义美元符号,因此您sed 's|EX_ROOT=/root/|EXROOT="/root/$SERVER"'在未设置的局部变量SERVER扩展为空字符串后运行。

ssh root@$HWNODEIP "sed 's|EX_ROOT=/root/\$SERVER|EX_ROOT=\"/root/\$SERVER\"|g' /etc/example/config.conf"
                                         ^
                                         |
                                 backslash here

但是,要就地编辑文件,请使用ed非标准sed扩展名-i.

printf 's|EX_ROOT=$SERVER|EX_ROOT="$SERVER"|g\nwq\n' |
    ssh root@$HWNODEIP 'ed /etc/example/config.conf'

由于ed不必从标准输入读取数据进行编辑,它可以从标准输入读取脚本,每行一个命令。语法本质上与sed. 但是,现在您需要的转义要少得多,因为脚本不会暴露给远程端的 shell。(如果wq命令看起来很熟悉,那是因为viis based on exwhich is based on ed。)


推荐阅读