如何用 sed 替换多行代码?

如何用 sed 替换多行代码?

我有一个大文件,其中包含特殊字符。那里有一个多行代码,我想用sed.

这:

  text = "\
    ------                                                           ------\n\n\
    This message was automatically generated by email software\n\
    The delivery of your message has not been affected.\n\n\
    ------                                                           ------\n\n"

需要变成这样:

text = ""

我尝试了以下代码,但没有运气:

sed -i '/  text = "*/ {N; s/  text = .*affected.\./  text = ""/g}' /etc/exim.conf

它不会替换任何内容,也不显示任何错误消息

我一直在玩它,但我尝试的一切都不起作用。

答案1

Perl 来拯救:

perl -i~ -0777 -pe 's/text = "[^"]+"/text = ""/g' input-file
  • -i~将“就地”编辑文件,并留下备份副本
  • -0777一次读取整个文件,而不是逐行读取

替换的s///工作方式与 sed 类似(即,它匹配text = "后面跟有除双引号之外的任何内容,多次直至双引号),但在这种情况下,它适用于整个文件。

答案2

您必须检查模式空间,N如果不匹配,则继续拉入 ext 行,例如

sed '/text = "/{              # if line matches text = "
:b                            # label b
$!N                           # pull in the next line (if not the last one)
/"$/!bb                       # if pattern space doesn't end with " go to label b
s/".*"/""/                    # else remove everything between the quotes
}' infile

gnu sed可以把它写成

sed '/text = "/{:b;$!N;/"$/!bb;s/".*"/""/}' infile

但这不是很有效,最好只选择范围/text = "/,/"/,修改第一行并删除其余的:

sed '/text = "/,/"/{            # in this range
/text = "/!d                    # delete all lines not matching text = "
s/\\/"/                         # replace the backslash with quotes (this is only
}' infile                       # executed if the previous d wasn't executed)

再次,gnu sed您可以将其写为一行:

sed '/text = "/,/"/{/text = "/!d;s/\\/"/}' infile

答案3

就我个人而言,我会用 Perl 来做这件事。如果我们可以假设"在结束之前没有",你可以这样做:

perl -0pe 's/(text\s*=\s*)".*?"/$1""/s' file

吞食-0整个文件,将其读入内存。意思-p是“在应用”给出的脚本后打印每一行(这里,“行”将是整个文件)-e。该脚本本身是一个简单的替换运算符。它将捕获text后跟 0 个或多个空白字符的字符串,然后=再捕获 0 个或多个空白字符 ( text\s*=\s*) 并将其保存为$1.然后,它将用模式 ( $1)和 替换捕获的模式以及它找到的最短带引号的字符串""。该s标志使.匹配换行符。

相关内容