grep与可选的前一段

时间:2014-07-30 23:45:38

标签: perl grep

我在perl脚本中有一个搜索查询$x,我想使用系统grep命令找到它。但是,我不仅要查找^$x(即锚定到该行的开头),还要查看substr($x,-$y)范围从$y到{$z的集合length($x) {1}}。如何执行这样的grep操作?

如果描述不清楚,我构建了一个问题的玩具示例。假设$x=ABCDEFGH$z=3,我希望找到包含^FGH$y=-3=-$z),^EFGH$y=-4)的一组表达式, ^DEFGH$y=-5),^CDEFGH$y=-6),^BCDEFGH$y=-7)和^ABCDEFGH({{1} })。

因此,来自以下文件:

$y=-8=-length($x)

返回的行将是1,3和6.不会返回第2行和第7行,因为模式未锚定到行的开头。不会返回第4行和第5行,因为不存在所需的最小子字符串(ABCDEFGH [1] ZABCDEFGH [2] EFGHUBZ [3] EFGDEB [4] FGABC [5] DEFGHEDBD [6] DEFGJEFGHO [7] )。

1 个答案:

答案 0 :(得分:1)

构建动态正则表达式

以下内容根据您的搜索条件动态构建正则表达式:

use strict;
use warnings;

# Search Criteria
my $search = 'ABCDEFGH';
my $min = 3;

# Build regex according to spec
my $regex = '^(?:' . join('|', $search =~ /(?=(.{$min,})$)/g) . ')';

# Search through DATA
while (<DATA>) {
    print if $_ =~ $regex;
}

__DATA__
ABCDEFGH    [1]
ZABCDEFGH   [2]
EFGHUBZ     [3]
EFGDEB      [4]
FGABC       [5]
DEFGHEDBD   [6]
DEFGJEFGHO  [7]

输出:

ABCDEFGH    [1]
EFGHUBZ     [3]
DEFGHEDBD   [6]

观察匹配的内容

还可以通过修改代码来观察匹配的内容,如下所示:

while (<DATA>) {
    print if s/($regex)/($1)/;
}

输出:

(ABCDEFGH)    [1]
(EFGH)UBZ     [3]
(DEFGH)EDBD   [6]

无需构建正则表达式的替代解决方案

如果选择字符串中不存在的分隔符(如\0),您也可以测试搜索字符串的结尾是否与行的开头匹配,如下所示:

while (<DATA>) {
    print if "$search\0$_" =~ /(.{$min,})\0\1/;
}