在Perl中,如何匹配多个前缀

时间:2014-06-05 15:12:24

标签: regex perl

我有2个输入文件。一个是前缀和长度列表,如下所示:

101xxx
102xxx
30xx
31xx

(其中x是任意数字)

另一个是数字列表。

我想迭代第二个文件,将每个数字与任何前缀/长度相匹配。这很容易。我构建了一个regexp列表:

my @regexps = ('101...', '102...', '30..', '31..');

然后:

foreach my $regexp (@regexps) {
    if (/$regexp/) {
        # do something

但是,正如你可以猜到的那样,对于很长的清单来说这很慢。

我可以将其转换为单个正则表达式:

my $super_regexp = '101...|102...|30..|31..';

...但是,我需要的是知道哪个正则表达式匹配该项目,以及...匹配的内容。

我试过了:

my $catching_regexp = '(101)(...)|(102)(...)|(30)(..)|(31)(..)';

但后来我不知道是看1美元,3美元,5美元还是7美元。

有什么想法吗?如何匹配任何这些前缀/长度,并知道哪个前缀,以及剩余的数字在哪里?

2 个答案:

答案 0 :(得分:3)

如果你的Perl足够新(5.10及更新版),你可以使用branch reset pattern

my $regex = qr/^(?|(101)(...)|(102)(...)|(30)(..)|(31)(..))$/;
while (<>) {
    print "$1, $2\n" if /$regex/;
}

答案 1 :(得分:1)

<强>更新

我想我错过了你想要的一些东西。如果不同的前缀具有不同的子表达式(... vs ..)并且您想要捕获/引用子表达式匹配的内容...您可以使用lookbehind:

((?<=101|102).{3}|(?<=30|31).{2})

这将捕获所有内容,如果它以101|102为前缀,则它将匹配3个字符;如果它以30|31作为前缀,则它将匹配2个字符。我们只使用一个捕获组,因此您的xxx始终位于$1

Demo

如果你还想捕捉前缀,你可以include a lazy capture group before the secondary grouping看守:

(.*?)((?<=101|102).{3}|(?<=30|31).{2})

您的前缀将在第1组中,而后缀则在第2组中。


在组内使用交替:

(101|102|30|31)...

这将创建一个额外捕获的组,但是你也可以使用“非捕获”组:

(?:101|102|30|31)...

Demo


你可以用这种心态做你想做的逻辑。它类似于您需要以任何语言对条件进行分组的方式:

if(a === true && (b === false || b === null)) {}