我有一个大文件,其中包含特殊字符。那里有一个多行代码,我想用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
标志使.
匹配换行符。