只有找到两个图案时,才能在两个线条图案之间打印

时间:2016-02-26 18:24:09

标签: bash sed

假设我有一个文件:

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

仅当找到sed/Start/时,我才想使用/End/在模式之间进行打印。

sed -n '/Start/,/End/p'按预期工作,如果您知道两个标记都在预期的顺序,但只是StartEnd打印到文件的末尾订购或不订购。 (即,在示例中打印第14行和第15行)

我试过了:

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

打印:

# 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

虽然接近但有两个问题:

  1. 不需要的前导空行
  2. 结束第7行打印两次
  3. 我希望得到类似于

    的结果
    $ 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
    

    (不需要块之间的空行......)

4 个答案:

答案 0 :(得分:2)

使用来自Solaris 11的GNU sed和sed:

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

输出:

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

如果找到Start 复制当前模式空间以保留空间(h)并跳转到脚本末尾(b)。对于每隔一行追加当前模式空间来保留空间(H)。如果找到End,则将保留空间复制回模式空间(g),然后打印模式空间(p)。

答案 1 :(得分:1)

你可以使用这个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

这是一个sed版本,可以在OSX(BSD)sedBased on Benjamin's sed command)上执行相同操作:

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

答案 2 :(得分:1)

GNU sed:遇到Start后,只要我们看不到End,就要继续添加行;一旦我们这样做,打印模式空间并重新开始:

$ 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

获取块之间的换行是很棘手的。这将在每个块之后添加一个,但最后会产生额外的空白:

$ 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]

答案 3 :(得分:0)

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

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