我正在尝试根据模式匹配替换两个连续的行,并希望重复整个文件。这是输入文件:
c aaaaa bbb
+ 0.1
c xxxx
c yyyy
+ 0.2
* c gggg
m eeeee hhhhh
+ 0.3
我试过的命令是:
sed '/^c/{N;s/+/*+/}'
我希望每行开头都会看到*
,但只有c
行后面的那些行:
c aaaaa bbb
*+ 0.1
c xxxx
c yyyy
*+ 0.2
* c gggg
m eeeee hhhhh
+ 0.3
我实际上得到了什么:
c aaaaa bbb
*+ 0.1
c xxxx
c yyyy
+ 0.2
* c gggg
m eeeee hhhhh
+ 0.3
在这里,我看到只有第一次出现+
(上一行以c开头)被*+
取代。文件中第二次出现的+
没有被替换。
我做错了什么?如何获得我想要的结果:替换发生在文件的多个连续行中?
答案 0 :(得分:2)
您遇到的问题是当以c
开头的行正好位于c
附带的另一行之后时,代码中的N
命令会消耗它,并且它在处理下一行时无法检查。
我没有提前读取以查看是否应该更改下一行,而是记得最后一行并回头查看是否应更改当前行:
sed 'x; G; /^c/ s/+/*+/; s/.*\n//' file
其工作原理如下:
x # Swap pattern space and hold buffer. Because we do this here,
# the previous line will be in the hold buffer for every line
# (except the first, then it is empty)
G # append hold buffer to pattern space. Now the pattern space
# contains the previous line followed by the current line.
/^c/ s/+/*+/ # If the pattern space begins with a c (i.e., if the previous
# line began with a c), replace + with *+
s/.*\n// # Remove the first line (the previous one) from the pattern
# space
# Then drop off the end. The changed current line is printed.
答案 1 :(得分:0)
sed -e 'H;$!d' -e 'x' -e ':cycle' -e 's/\(\nc[[:alnum:][:blank:][:punct:]]*\n\)+/\1*+/g;t cycle' -e 's/.//' YourFile
Posix版本在最大2个内部循环中更改whoe
-e 'H;$!d' -e 'x'
)+
(c
)s/\(\nc[[:alnum:][:blank:][:punct:]]*\n\)+/\1*+/g
开头的行前面添加*
:cycle
和t cycle
)H
将当前行追加到缓冲区也为第一行添加额外的新行作为标题)(对于带有c
的第一行)并删除此最后('s/.//
)