sed 替换包含新行的文本

sed 替换包含新行的文本

我有一个用于在我的 Ubuntu 服务器上安装 Web 服务器的 bash 脚本。

我想在 /etc/apache2/apache2.conf 中替换

#ServerRoot "/etc/apache2"

#

经过

#ServerRoot "/etc/apache2"
ServerName localhost

#

如果我做

sed -i 's|#ServerRoot "/etc/apache2"|#ServerRoot "/etc/apache2"\nServerName localhost|' /etc/apache2/apache2.conf

它可以工作,但我想在 #ServerRoot 后面包含空白行和 #,以避免在脚本执行两次时添加两次 ServerName。

我试过

sed -i 's|#ServerRoot "/etc/apache2"\n\n#|#ServerRoot "/etc/apache2"\nServerName localhost\n\n#|' /etc/apache2/apache2.conf

但它不起作用。

答案1

怎么样

  1. 搜索#ServerRoot "/etc/apache2"
  2. 如果找到,则读取下一行并将其附加到 sed 的模式空间中
  3. 在附加的模式空间中搜索换行符后的空行,并替换ServerName localhost

综合起来,

sed -i '\|#ServerRoot "/etc/apache2"| {N;s|\n$|\nServerName localhost|}' /etc/apache2/apache2.conf

如果“空”行实际上包含空格,您可以将其修改为

sed -i '\|#ServerRoot "/etc/apache2"| {N;s|\n\s*$|\nServerName localhost|}' /etc/apache2/apache2.conf

答案2

终于在帮助\n下完成了复查sed由此. 有点拗口:

sed -Ei ':a;N;$!ba;s/^(#ServerRoot[^\n]*)\n\n/\1\nServerName localhost\n\n/' apache2.conf

还有一个 awk 可以做同样的事情(在我看来,它更长但更容易理解)。 逻辑和sponge解释在最后一节中。

awk '{print}/^#ServerRoot/{getline; if($0=="") print "ServerName localhost"; print}' apache2.conf | sponge apache2.conf

编辑:这sed并不像我最初想象的那么难。你只需要匹配并附加(命令a);你不需要替换。我已经测试了以下内容:

sed -i '/^#ServerRoot/a ServerName localhost' apache2.conf

如果愿意的话,你可以更具体地说明你的比赛情况,awk为了后人的利益,我将保留下面的内容。


编辑相当简单,awk但为了写回到同一个文件,我们要么需要一个临时的中间文件,要么sponge(从moreutils包中)。我将展示这两种方法。

awk '{print}/^#ServerRoot/{print "ServerName localhost"}' apache2.conf > tmp
mv tmp apache2.conf

或者

awk '{print}/^#ServerRoot/{print "ServerName localhost"}' apache2.conf | sponge apache2.conf

只是awk打印它找到的每一行,但如果匹配,^#ServerName则会写入您的 ServerName 行。我发现这种处理比使用 sed 进行任意“交换”更容易阅读。

答案3

另一种方法(感谢 muru),但由于不使用 sed 而有点脱离上下文:

为了Ubuntu 14.04

创建文件 完全限定域名配置文件丹斯/etc/apache2/conf-可用/包含

ServerName localhost

在 /etc/apache2/conf-enabled/ 中创建符号链接

sudo ln -s /etc/apache2/conf-available/fqdn.conf /etc/apache2/conf-enabled/fqdn.conf

相关内容