2015-05-23 46 views
2

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

例如我有一个文件,需要提取“proc sql”和(“quit”或“run”)之间的所有内容,其中包含“index”。

 
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” 和 “退出”(而不是 “退出” 之间或提取“运行”),包含“索引”。我不知道如何添加OR操作。

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

+0

对不起,改正了。 – kyarovoy

回答

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 
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 
相关问题