我已经非常接近我的目标了,但我现在陷入了困境。
我正在尝试创建一个自动化脚本来对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
其上stdin
。sed
也可以在其参数列表中获取文件名或使用<
运算符。
不要将在命令行上引用字符视为您的责任。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我还没有测试过它,因为我远离我的终端。