根据模式替换两个连续的行并重复整个文件

时间:2015-09-16 13:44:20

标签: sed

我正在尝试根据模式匹配替换两个连续的行,并希望重复整个文件。这是输入文件:

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开头)被*+取代。文件中第二次出现的+没有被替换。

我做错了什么?如何获得我想要的结果:替换发生在文件的多个连续行中?

2 个答案:

答案 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开头的行前面添加*
  • 如果在上一行(:cyclet cycle
  • 中发生,则执行相同的操作
  • 使用技巧确保以新行开头(H将当前行追加到缓冲区也为第一行添加额外的新行作为标题)(对于带有c的第一行)并删除此最后('s/.//