简体   繁体   English

sed仅在找到两个线型之间打印

[英]sed print between two line patterns only if both patterns are found

Suppose I have a file with: 假设我有一个文件:

Line 1
Line 2
Start Line 3
Line 4 
Line 5
Line 6
End  Line 7
Line 8
Line 9
Start Line 10
Line 11
End Line 12
Line 13
Start line 14
Line 15

I want to use sed to print between the patterns only if both /Start/ and /End/ are found. 我想仅在同时找到/Start//End/情况下使用sed在模式之间进行打印。

sed -n '/Start/,/End/p' works as expected if you know both markers are there and in the order expected, but it just prints from Start to the end of the file if End is either out of order or not present. sed -n '/Start/,/End/p'如预期的那样工作,如果您知道两个标记都在里面并按预期的顺序进行,但是如果End是否乱序,它只会从Start打印到文件的End当下。 (ie, prints line 14 and line 15 in the example) (即,在示例中打印第14行和第15行)

I have tried: 我努力了:

sed -n '/Start/,/End/{H;}; /End/{x; p;}' file

Prints: 打印:

# blank line here...
Start Line 3
Line 4 
Line 5
Line 6
End  Line 7
End  Line 7
Start Line 10
Line 11
End Line 12

which is close but two issues: 这很接近,但是有两个问题:

  1. Unwanted leading blank line 不需要的前导空白行
  2. End Line 7 printed twice 结束线7打印两次

I am hoping for a result similar to 我希望得到类似的结果

$ awk '/Start/{x=1} x{buf=buf$0"\n"} /End/{print buf; buf=""; x=0}' file
Start Line 3
Line 4 
Line 5
Line 6
End  Line 7

Start Line 10
Line 11
End Line 12

(blank lines between the blocks not necessary...) (块之间不需要空白线...)

With GNU sed and sed from Solaris 11: 使用GNU sed和从Solaris 11 sed:

sed -n '/Start/{h;b;};H;/End/{g;p;}' file

Output: 输出:

Start Line 3
Line 4 
Line 5
Line 6
End  Line 7
Start Line 10
Line 11
End Line 12

If Start is found copy current pattern space to hold space ( h ) and branch to end of script ( b ). 如果找到“ Start ,请复制当前模式空间以保留空间( h )并跳转至脚本结尾( b )。 For every other line append current pattern space to hold space ( H ). 对于每隔一行, 附加当前模式空间以保留空间( H )。 If End is found copy hold space back to pattern space ( g ) and then print pattern space ( p ). 如果找到“ End则将保留空间复制回图案空间( g ),然后打印图案空间( p )。

You can use this awk: 您可以使用以下awk:

awk 'x{buf=buf ORS $0} /Start/{x=1; buf=$0} /End/{print buf; buf=""; x=0}' file

Start Line 3
Line 4
Line 5
Line 6
End  Line 7
Start Line 10
Line 11
End Line 12

Here is a sed version to do the same on OSX (BSD) sed ( Based on Benjamin's sed command ): 这是一个在OSX(BSD) sed上执行相同操作的sed版本( 基于Benjamin的sed命令 ):

sed -n -e '/Start/{:a;' -e 'N;/End/!ba;' -e 'p;}' file

GNU sed: after encountering Start , keep appending lines as long as we don't see End ; GNU sed:遇到Start ,请继续添加行,直到我们看不到End once we do, print the pattern space and start over: 完成后,打印图案空间并重新开始:

$ sed -n '/Start/{:a;N;/End/!ba;p}' infile
Start Line 3
Line 4 
Line 5
Line 6
End  Line 7
Start Line 10
Line 11
End Line 12

Getting the newline between blocks is tricky. 在块之间获取换行符非常棘手。 This would add one after each block, but results in an extra blank at the end: 这将在每个块之后添加一个,但最后会导致一个额外的空白:

$ sed -n '/Start/{:a;N;/End/!ba;s/$/\n/p}' infile
Start Line 3
Line 4 
Line 5
Line 6
End  Line 7

Start Line 10
Line 11
End Line 12
[blank]

就个人而言,我更喜欢您的awk解决方案,但是:

  sed -n -e '/start/,/end/H' -e '/end/{s/.*//; x; p}' input

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM