使用 sed 替换多行
Posted
技术标签:
【中文标题】使用 sed 替换多行【英文标题】:Replacing multiple lines using sed 【发布时间】:2022-01-19 18:13:50 【问题描述】:美好的一天!
我试图弄清楚hold space
和pattern space
在sed
中的工作原理,以便我可以用它来替换多个字符串。
例如,如果要将第一行和第二行替换为NEW STRING
:
echo -e "aa\nbb\ncc\ndd\n"
aa
bb
cc
dd
为了得到这样的STDOUT:
NEW STRING
NEW STRING
cc
dd
我正在尝试做类似的事情:
echo -e "aa\nbb\ncc\ndd\n" | sed -e 'commands'
我知道可以这样做:
echo -e "aa\nbb\ncc\ndd\n" | tr '\n' '\0' | sed -e 's#aa#NEW STRING#;s#bb#NEW STRING#' | tr '\0' '\n'
NEW STRING
NEW STRING
cc
dd
但是不使用tr
怎么解决这个问题呢?
您能否提出一个我们不知道行号的案例?我们只知道aa
在bb
之后。
【问题讨论】:
【参考方案1】:sed
命令接受一系列要操作的行:
$ printf "%s\n" aa bb cc dd | sed '1,2s/.*/NEW STRING/'
NEW STRING
NEW STRING
cc
dd
有些像s
处理范围内的单个行,有些则将整个范围视为一个块以将命令应用于:
$ printf "%s\n" aa bb cc dd | sed '1,2c\
NEW STRING'
NEW STRING
cc
dd
例如,一行是aaa,另一行是bbb。我们知道 aaa 在 bbb 之前,但我们不知道他们在文件中的编号。
我总结的一种方法(可能会有更好的方法;并且仅使用 GNU sed
进行了测试)
$ printf "%s\n" qq rr aa bb cc aa xx dd |
sed '/^aa$/N; /^aa\nbb$/s/.*/NEW STRING\nNEW STRING/; p; d; P; D'
qq
rr
NEW STRING
NEW STRING
cc
aa
xx
dd
如果当前行是aa,N
将下一行追加到当前模式空间。如果它现在是 aa\nbb,则用两行 NEW STRING 行替换它,打印出模式空间,将其删除并重新开始。如果模式空间有其他内容,则打印出第一个换行符之前的所有内容,从模式空间中删除该文本,然后从 N
读取的第二行重新开始。
【讨论】:
如果我们不知道行号,但我们知道需要用正则表达式替换行怎么办?例如,一行是aaa
,另一行是bbb
。我们知道aaa
在bbb
之前,但我们不知道文件中它们的编号。 bbb
位于 aaa
之后。谢谢!
@alex2020:如果您自己指定这些要求会更好。
@alex2020 查看编辑。
最后的解决方案可能是sed '/^aa/N;/^bb/M!P;D;s/.*/new string/p' file
?【参考方案2】:
如果目标是试验模式空间和保持空间,那么这就是一个例子:
echo -e "aa\nbb\ncc\ndd" | sed '1 s/.*/NEW STRING/; h; 2g'
输出:
新字符串 新字符串 抄送 dd将第一行替换为 NEW STRING
,然后复制模式空间以保留空间 (h
)。在第二行将保持空间复制到模式空间 (g
)。
【讨论】:
以上是关于使用 sed 替换多行的主要内容,如果未能解决你的问题,请参考以下文章