我有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美元。
有什么想法吗?如何匹配任何这些前缀/长度,并知道哪个前缀,以及剩余的数字在哪里?
答案 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
。
如果你还想捕捉前缀,你可以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)...
你可以用这种心态做你想做的逻辑。它类似于您需要以任何语言对条件进行分组的方式:
if(a === true && (b === false || b === null)) {}