两个分隔符之间的unix打印后跟着匹配的单词

时间:2015-09-02 00:07:17

标签: regex perl unix awk

我有以下文字

Start
bla
bla
bla
end
Start
bla
bla
MATCH
bla
end
Start
bla
bla
bla
end

我只需要下面的

Start
bla
bla
MATCH
bla
end

用英文写的。在两个模式之间打印行,其中包括一个匹配字符串。

尝试

awk '/Start /,/End/' file

perl -lne 'print if  /start/ .. /end/' file

无法在标签之间进行匹配

首选需要一个班轮命令

4 个答案:

答案 0 :(得分:1)

将输入记录分隔符(from inspect import signature def decorator(f): @functools.wraps(f) def wrapper(*args, **kwargs): return f(*args, **kwargs) wrapper.__signature__ = signature(f) return wrapper )设置为$/,然后对end\n的正则表达式检查将检查MATCHStart之间的每个部分为如果它是单行。

end\n

答案 1 :(得分:1)

您遇到的问题是您的范围运算符仍然可以逐行运行。

E.g。

while ( <> ) {
    print if m/start/i .. m/end/i; 
}

仍然使用记录分隔符作为\n - 循环的每次迭代都将从文件中读取另一行,但您无法匹配整个块...因为它可能不会已经预知到目前为止。

你可以通过正则表达式匹配&#39;开始..结束&#39;块:

#!/usr/bin/env perl
use strict;
use warnings;

my @chunks = do { local $/; <DATA> =~ m/Start.*?end/mgs };
print grep { m/MATCH/ } @chunks;

__DATA__
Start
bla
bla
bla
end
Start
bla
bla
MATCH
bla
end
Start
bla
bla
bla
end

或者作为另一张海报备注 - 将$/设置为&#39;结束&#39;。这有一点点缺点,因为它会忽略“开始”,这意味着如果您没有正确匹配,可能会获得额外的内容。

您也可以尝试:

local $/ = "end\nStart"; 

哪个会正确分割您的数据,但是再次 - 可能无法正确处理所有方案。

#!/usr/bin/env perl
use strict;
use warnings;

local $/ = "end\nStart";

while ( <DATA> ) {
    chomp; 
    print "Chunk: $_\n";
    print "----\n";
    print "Matches!\n" if m/MATCH/;
}

这些可以单行:

perl -lne 'BEGIN { $/ = "end\nStart" } print if /MATCH/' file

答案 2 :(得分:0)

要求救援

awk 'BEGIN {ORS=RS="end\n"} /MATCH/'

按照定义设置记录分隔符并查找匹配的记录。如果不需要多个匹配,则只打印第一个匹配。

awk 'BEGIN {ORS=RS="end\n"} /MATCH/{print;exit}'

答案 3 :(得分:0)

假设:

$ echo "$tgt" 
Start
bla
bla
bla
end
Start
bla
bla
MATCH
bla
end
Start
bla
bla
bla
end

您可以'啜饮'该文件,然后测试MATCH的每个匹配组:

$ echo "$tgt" | perl  -0777 -lne 'for (/^Start.*?^end/msg) { print if /^MATCH/m; }'
Start
bla
bla
MATCH
bla
end

也适用于文件。