sed sh 转义问题

sed sh 转义问题

我已经非常接近我的目标了,但我现在陷入了困境。

我正在尝试创建一个自动化脚本来对phpmyadmin配置文件进行一些简单的编辑。

cat /usr/share/phpmyadmin/config.sample.inc.php |sed s^//\ \$cfg\\[\'Servers\'^\$cfg\\[\'Servers\'^

基本上我试图删除//所有以 开头的行// $cfg['Servers']。上面的行确实做到了这一点,但我对我必须做的所有转义感到不满意。我已经尝试了这个 sed 命令的数百种变体,但转义所有其他字符似乎是迄今为止唯一有效的方法。

另一个障碍是:最终我想通过提升的 shell(使用sudo sh -c)传递上述命令字符串,例如:

sudo sh -c "cat /usr/share/phpmyadmin/config.sample.inc.php |sed s^//\ \$cfg\\[\'Servers\'^\$cfg\\[\'Servers\'^  >/usr/share/phpmyadmin/config.inc.php"

但每次我尝试这样做时,都会收到此错误:

sed: -e expression #1, char 27: unterminated `s' command

所以我的问题是:我可以简化我的sed表达式,这样我就不需要转义这么多字符,以及如何将其传递到提升的 shell,这样它就不会破坏我的sed s命令?

我认为我的主要问题是提升的 shell 传递了一个由双引号分隔的字符串,而 sed 字符串包含单引号。过去,我通常没有同时使用这两种命令的命令,因此我可以用其中一种替代另一种。

答案1

如果脚本正确用双引号括起来,则无需转义空格和单引号:

sed "s^// \$cfg\['Servers'^\$cfg['Servers'^" file

另外,替换中的支架不需要转义。正则表达式中的括号确实需要转义,因为否则它会被理解为特殊的正则表达式符号。

为了最大程度地减少转义,最好的方法是将sed命令放在一个文件中,这样我们就不需要双引号,也不需要保护$替换中的美元符号免受shell扩展。

servers.sed

s^// \$cfg\['Servers'^$cfg['Servers'^

然后这样运行:

sed -f servers.sed file

最后一种形式也很容易在提升的 shell 中使用:

sudo sh -c 'sed -f servers.sed file > newfile'

答案2

以下是一些可能有助于简化问题的观察结果。

无需创建cat文件然后将其呈现在sed其上stdinsed也可以在其参数列表中获取文件名或使用<运算符。

不要将在命令行上引用字符视为您的责任。shell如果您将命令用引号引起来,这就是 的工作。

现在,由于命令中已经存在单引号,sed因此使用双引号很容易。

  • 但随后我们需要关闭双引号内插值$解释的字符shell
  • 括号[需要加引号,以预期它会被 解释为文字sed

这就解决了这个shell问题。sed现在让我们看一下 命令。

在这里,您不必要地重复替换部分。由于您的目标只是去除前导双斜杠,因此我们应该使用命令/selectline/s/pat/repl/的形式s///

由于该行已被选中,我们知道前 3 个字符是什么:// 和一个空格。

该命令中潜伏着一个微妙的错误sed。由于您选择使用^作为替换命令分隔符,因此它不再充当行首字符。

regex术语而言,这意味着该行中任何位置的双斜杠都可以进行更改。显然这不是你的规范所说的。所以我们使用不同的分隔符|

 base=/usr/share/phpmyadmin
 if=$base/config.sample.inc.php
 of=$base/config.inc.php
 < "$if" \
    sed -e "\\|^// \$cfg\\['Servers']|s/...//" \
 > "$of" 

您还可以使用单引号 sed 命令行来稍微减少反斜杠负载:

sed -e '\|^// $cfg\['\''Servers'\'']|s/...//' 

现在进入sudo部分。您将sed命令作为字符串传递给shell解释器。相反,我们可以shell's stdin通过 heredoc运算符传递命令<<

sudo sh <<\eof
base=/usr/share/phpmyadmin
if=$base/config.sample.inc.php
of=$base/config.inc.php
< "$if" sed -e "\\|^// \$cfg\\['Servers']|s/...//" > "$of"
eof

华泰

PS我还没有测试过它,因为我远离我的终端。

相关内容