Grep从固定文本开始,直到第一个空白行


9

我有一个prova.txt像这样的文件:

Start to grab from here: 1
fix1
fix2
fix3
fix4
random1
random2
random3
random4

extra1
extra2
bla

Start to grab from here: 2
fix1
fix2
fix3
fix4
random1546
random2561

extra2
bla
bla

Start to grab from here: 1
fix1
fix2
fix3
fix4
random1
random22131

我需要从“开始抢在这里”到第一个空白行。输出应如下所示:

Start to grab from here: 1
fix1
fix2
fix3
fix4
random1
random2
random3
random4

Start to grab from here: 2
fix1
fix2
fix3
fix4
random1546
random2561

Start to grab from here: 1
fix1
fix2
fix3
fix4
random1
random22131

如您所见,“开始抓住这里”之后的行是随机的,因此-A -B grep标志不起作用:

cat prova.txt | grep "Start to grab from here" -A 15 | grep -B 15 "^$" > output.txt

您能帮助我找到一种方法来捕获将要抓取的第一行(如“从此处开始抓取”),直到出现空白行。我无法预测“从这里开始抓取”之后我会有多少条随机线。

任何与unix兼容的解决方案都值得赞赏(grep,sed,awk比perl或类似的更好)。

编辑:@ john1024的出色回应后,我想知道是否有可能:

1°对块进行排序(根据从此处开始抓取:1然后1然后2)

2°删除4条(按字母顺序随机排列)的线fix1,fix2,fix3,fix4,但始终为4

3°最终删除了随机的重复项,例如sort -u命令

最终输出应如下所示:

# fix lines removed - match 1 first time
Start to grab from here: 1
random1
random2
random3
random4

#fix lines removed - match 1 second time
Start to grab from here: 1
#random1 removed cause is a dupe
random22131

#fix lines removed - match 2 that comes after 1
Start to grab from here: 2
random1546
random2561

要么

# fix lines removed - match 1 first time and the second too
Start to grab from here: 1
random1
random2
random3
random4
#random1 removed cause is a dupe
random22131

#fix lines removed - match 2 that comes after 1
Start to grab from here: 2
random1546
random2561

第二个输出比第一个更好。还需要其他一些Unix命令魔术。


1
这对于从java jstack输出获取特定线程的堆栈跟踪非常有帮助。很高兴我找到了这个问答!
BenjaminBallard '18

Answers:


13

使用awk

尝试:

$ awk '/Start to grab/,/^$/' prova.txt
Start to grab from here: 1
random1
random2
random3
random4

Start to grab from here: 2
random1546
random2561

Start to grab from here: 3
random45
random22131

/Start to grab/,/^$/定义范围。它以任何与之匹配的行开头,Start to grab并以其后的第一个空行结尾^$

使用sed

具有非常相似的逻辑:

$ sed -n '/Start to grab/,/^$/p' prova.txt
Start to grab from here: 1
random1
random2
random3
random4

Start to grab from here: 2
random1546
random2561

Start to grab from here: 3
random45
random22131

-n告诉sed除非我们明确要求,否则不要打印任何内容。 /Start to grab/,/^$/p告诉它打印在定义的范围内的任何行/Start to grab/,/^$/


您的解决方案是完美的,我已编辑要求添加的内容。珍惜您的帮助。谢谢
heisen

1

我正在发布替代解决方案,因为它可能对某些人的用例有用。此解决方案不完全符合规定的要求,有关最佳解决方案,请参见@ John1024的答案。

您可以将awk与Record Separator设置为空字符串一起使用,awk会将其解释为空白换行符:

$ awk '/Start/' RS= prova.txt 
Start to grab from here: 1
fix1
fix2
fix3
fix4
random1
random2
random3
random4
Start to grab from here: 2
fix1
fix2
fix3
fix4
random1546
random2561
Start to grab from here: 1
fix1
fix2
fix3
fix4
random1
random22131

此版本不会在输出中保留空白换行符。如果存在,它将在比赛之前显示上下文。grepping文件中的某些内容时,此行为可能非常有用,并且您希望查看换行符分隔的块是其中的一部分,例如:

$ awk '/random1546/' RS= prova.txt 
Start to grab from here: 2
fix1
fix2
fix3
fix4
random1546
random2561

例如,当对ini文件中的内容进行grep处理时,我发现这很有用。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.