将行插入已知的文本块

时间:2009-07-08 00:37:42

标签: regex bash sed

我将文本的“块”定义为文件开头,换行符或文件结尾之间的所有行:

block1
block2
block3

anotherblock4
anotherblock5
anotherblock6

lastblock7
lastblock8

任何文字都可以占据一个区块 - 不知道有哪些线条。 我试着编写一个shell脚本在第二个块中插入一个新行,但由于sed不喜欢使用换行符,我在这个sed oneliner上乱砍了:

sed -n "H;\${g;s/\n\n/\nTEST\n\n/2;p}"

这导致:

[newline]
block1
block2
block3

anotherblock4
anotherblock5
anotherblock6
TEST

lastblock7
lastblock8

问题是,它在缓冲区的开头添加了一个换行符(标记为[newline],因为StackOverflow的标记无法显示) 有没有其他方法可以使用不同的工具或不同的正则表达式来完成它?

4 个答案:

答案 0 :(得分:2)

这可以满足您的需求,并在开头摆脱不需要的newline

sed -n "1{x;d};H;\${g;s/\n\n/\nTEST\n\n/2;p}"

答案 1 :(得分:1)

这是一种可能的解决方案

awk '/^$/{f++}f==2{print "TEST\n";f=0;next}1' file

答案 2 :(得分:0)

好吧,这不是我最骄傲的时刻,但我认为它能做你想要的......也许吧?我无法让sed做任何有用的事情,因为至少在我的机器上,它不喜欢在s/x/y替换命令中使用换行符。

# cat blocks
block1
block2
block3

anotherblock4
anotherblock5
anotherblock6

lastblock7
lastblock8
# python -c 'import sys,re; print re.sub("(\n\n[\s\S]*?\n)(\n)", "\\1TEST\n\\2", sys.stdin.read(), 1),' < blocks
block1
block2
block3

anotherblock4
anotherblock5
anotherblock6
TEST

lastblock7
lastblock8

注意:

  • 没有相当于sed的“替换第二匹配”选项,所以我需要一个更复杂的正则表达式。
  • .与换行符不匹配,因此[\s\S]
  • ?使*非贪婪。
  • 1的第4个参数将此限制为单个替换。
  • 最后的逗号会禁止print添加额外的换行符。

或者,您可以在几乎但不太正确的| tail +2命令后点击“sed”来切断第一行输出。

答案 3 :(得分:0)

还有一个awk解决方案。这要求awk跟踪段落,而不是像ghostdog74的解决方案那样自己计算段落。

awk -v 'RS=\n\n' '{print}NR==2{print"TEST"}{print""}'