我想检查一些字符串是否与给定的一组正则表达式匹配。我怎么能这样做?
答案 0 :(得分:20)
如果您使用的是perl版本5.10或更高版本,请使用智能匹配!
#! /usr/bin/env perl
use warnings;
use strict;
use feature 'switch';
my @patterns = (
qr/foo/,
qr/bar/,
qr/baz/,
);
for (qw/ blurfl bar quux foo baz /) {
no warnings 'experimental::smartmatch';
print "$_: ";
given ($_) {
when (@patterns) {
print "hit!\n";
}
default {
print "miss.\n";
}
}
}
虽然您没有看到明确的~~
运算符,Perl's given
/when
会在幕后执行:
大部分力量来自隐式智能匹配,有时可以应用。大多数情况下,
when(EXPR)
被视为$_
的隐式智能匹配,即$_ ~~ EXPR
。 (有关智能匹配的更多信息,请参阅Smartmatch Operator in perlop。)
“Smartmatch Operator” in perlop提供了您可以使用的许多组合的表格,上面的代码对应于$a
任何且$b
是数组,大致对应
grep $a ~~ $_, @$b
除了搜索短路即之外,在匹配时快速返回,而不是处理所有元素。在隐式循环中,我们智能匹配任何与 Regex ,这是
$a =~ /$b/
输出:
blurfl: miss. bar: hit! quux: miss. foo: hit! baz: hit!
由于这个答案最初编写,Perl的设计师已经意识到智能匹配的工作方式存在错误,因此它是now considered an experimental feature。上面使用的案例不是有争议的用途之一,尽管如此,除了我添加given is experimental
之外,代码的输出还包括when is experimental
和no warnings 'experimental::smartmatch';
。
任何使用实验性功能都会带来一些风险,但我估计这种情况的可能性很小。当使用类似于上面的代码并升级到更新版本的Perl时,这是一个潜在的问题需要注意。
答案 1 :(得分:12)
从perlfaq6回答How do I efficiently match many regular expressions at once?,在这种情况下,我刚刚使用智能匹配示例更新了最新的开发版本。
如何有效地匹配多个正则表达式?
(由brian d foy提供)
如果你有Perl 5.10或更高版本,这几乎是微不足道的。你很聪明 匹配正则表达式对象数组:
my @patterns = ( qr/Fr.d/, qr/B.rn.y/, qr/W.lm./ );
if( $string ~~ @patterns ) {
...
};
智能匹配在找到匹配时停止,因此不必尝试 每一个表达。
早于Perl 5.10,你需要做一些工作。你想要 避免每次想要匹配时编译正则表达式。 在这个例子中,perl必须为每个重新编译正则表达式 迭代的C循环,因为它无法知道什么 C将是:
my @patterns = qw( foo bar baz );
LINE: while( <DATA> ) {
foreach $pattern ( @patterns ) {
if( /\b$pattern\b/i ) {
print;
next LINE;
}
}
}
C运营商出现在perl 5.005。它编译常规 表达式,但不适用它。当你使用预编译 正则表达式的版本,perl做的工作较少。在这个例子中,我插入了 C将每个模式转换为预编译形式。其余的 脚本是相同的,但速度更快:
my @patterns = map { qr/\b$_\b/i } qw( foo bar baz );
LINE: while( <> ) {
foreach $pattern ( @patterns ) {
if( /$pattern/ )
{
print;
next LINE;
}
}
}
在某些情况下,您可以将多个模式合并为一个 正则表达式。注意需要回溯的情况 虽然。
my $regex = join '|', qw( foo bar baz );
LINE: while( <> ) {
print if /\b(?:$regex)\b/i;
}
有关正则表达效率的更多详细信息,请参阅Jeffrey Freidl撰写的I.他解释了如何定期 表达式引擎工作以及为什么某些模式令人惊讶 效率低下。一旦你理解了perl如何应用正则表达式, 你可以针对个别情况调整它们。
答案 2 :(得分:10)
我一次性测试多个正则表达式的值是Regexp::Assemble,它将“将多个正则表达式组装成单个RE”,其方式比简单地执行{{1}更加智能和优化}}。默认情况下,您还可以检索匹配的文本部分,如果您需要知道匹配的模式,join '|', @regexps
开关将提供该信息。它的性能非常好 - 在一个应用程序中,我用它来同时测试1700个模式 - 我还没有需要它不做的任何事情。
答案 3 :(得分:3)
我不确定你在寻找什么,但是那样的东西?
#!/usr/bin/perl
@regexes = ( qr/foo/ , qr/bar/ );
while ($line=<>){
chomp $line;
$match=0;
for $re (@regexes){
$match++ if ($line =~ $re);
}
print "$line matches $match regexes\n";
}
你也可以把它们全部编译成一个像这样的单一的:
#!/usr/bin/perl
@regexes = ( qr/foo/ , qr/bar/ );
$allre= "(".join("|",@regexes).")";
$compiled=qr/$allre/;
while(<>){
chomp;
print "$_ matches ($1)\n" if /$compiled/;
}
希望有所帮助。
答案 4 :(得分:3)
如果使用大量regexp,您可能会对Regexp::Optimizer
感兴趣从概要部分看:
use Regexp::Optimizer;
my $o = Regexp::Optimizer->new;
my $re = $o->optimize(qr/foobar|fooxar|foozap/);
# $re is now qr/foo(?:[bx]ar|zap)/
如果您愿意安装额外的模块,那可能会更有效率。