提取包含D的A和(B或C)之间的线

时间:2015-05-23 16:57:16

标签: bash perl awk sed grep

我需要在A和(B或C)模式之间提取文本,其中包含D模式。

例如我有一个文件,需要在" proc sql"之间提取所有文件。和("退出"或"运行"),包含"索引"内部。

proc sql
bla-bla-bla
index=10;
quit

proc sql
bla-bla-bla
quit;

proc sql
index=10;
run

需要输出:

proc sql
bla-bla-bla
index=10;
quit

proc sql
index=10;
run

到现在为止我有这样的解决方案:

perl -0777 -lne 'print for grep /\bindex\b/i, /^proc sql.*?quit.*?\n/mgs' file

但它只提取" proc sql"和"退出" (不是"退出"或"运行"),包含" index"。我不知道如何添加OR操作。

如果你可以提出替代的awk / sed / grep解决方案 - 会很好。

2 个答案:

答案 0 :(得分:0)

这会按照你的要求行事。它累积到$block开始和结束模式之间的所有行。到达结束模式时,如果它包含index

,则会打印该块
use strict;
use warnings;

my $block;

while ( <DATA> ) {
  my $state = /^proc sql\b/ .. /^(?:quit|run)\b/;
  $block .= $_ if $state;
  if ( $state =~ /E/ ) {
    print $block, "\n" if $block =~ /^index=/m;
    $block = '';
  }
}

__DATA__
proc sql
bla-bla-bla
index=10;
quit

proc sql
bla-bla-bla
quit;

proc sql
index=10;
run

<强>输出

proc sql
bla-bla-bla
index=10;
quit

proc sql
index=10;
run

答案 1 :(得分:0)

鉴于您的输入文件名为input.txt,这将在awk中解决它:

awk 'BEGIN {
    procDetected = 0;
    indexDetected = 0;
}

/proc/ {
    buffer = "";
    indexDetected = 0;
    procDetected = 1;
}

/index/ {
    indexDetected = 1;
}

{
    if (procDetected) {
        # Add the line to the buffer.
        buffer = buffer $0 "\n";
    }
}

/run/ || /quit/ {
    if (procDetected && indexDetected) {
        print buffer;
    }
    procDetected = 0;
    indexDetected = 0;
}' input.txt