如何在Perl中匹配多个正则表达式?

Dav*_*d B 14 regex perl

我想检查一些字符串是否与给定的一组正则表达式匹配.我怎样才能做到这一点?

Gre*_*con 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";
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

虽然你没有看到一个显式的~~运算符,Perl's given/when在幕后做了:

大多数力量来自隐式智能匹配,有时可以应用.大多数时候,when(EXPR)被视为隐含的智能匹配$_,即$_ ~~ EXPR.(有关智能匹配的更多信息,请参阅perlop中的Smartmatch Operator.)

"Smartmatch操作员"在perlop中给你可以使用许多组合的表,和上述代码对应于其中的情况下$a任何$b数组,其大致对应于

grep $a ~~ $_, @$b
Run Code Online (Sandbox Code Playgroud)

除了搜索短路,在匹配上快速返回而不是处理所有元素.在隐式循环中,我们智能匹配任何反对正则表达式,这是

$a =~ /$b/
Run Code Online (Sandbox Code Playgroud)

输出:

blurfl: miss.
bar: hit!
quux: miss.
foo: hit!
baz: hit!

附录

由于这个答案最初编写,Perl的设计师已经意识到智能匹配的工作方式存在错误,因此它现在被认为是一个实验性功能.上面使用的案例不是有争议的用途之一,尽管如此,代码的输出将包括given is experimentalwhen is experimental我添加的除外no warnings 'experimental::smartmatch';.

任何使用实验性功能都会带来一些风险,但我估计这种情况的可能性很小.当使用类似于上面的代码并升级到更新版本的Perl时,这是一个潜在的问题需要注意.

  • 这场聪明的比赛非常酷.我从来没有想过做那样的事情.我今天晚些时候会在FAQ中添加一个类似的例子.:) (2认同)

bri*_*foy 12

perlfaq6的答案我如何有效地匹配多个正则表达式?,在这种情况下,我刚刚用智能匹配示例更新的最新开发版本.


如何有效地匹配多个正则表达式?

(由brian d foy提供)

如果你有Perl 5.10或更高版本,这几乎是微不足道的.您只需与正则表达式对象数组进行智能匹配:

my @patterns = ( qr/Fr.d/, qr/B.rn.y/, qr/W.lm./ );

if( $string ~~ @patterns ) {
    ...
    };
Run Code Online (Sandbox Code Playgroud)

智能匹配在找到匹配时停止,因此不必尝试每个表达式.

早于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;
            }
        }
    }
Run Code Online (Sandbox Code Playgroud)

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;
            }
        }
    }
Run Code Online (Sandbox Code Playgroud)

在某些情况下,您可以将多个模式组合成一个正则表达式.请注意需要回溯的情况.

my $regex = join '|', qw( foo bar baz );

LINE: while( <> ) {
    print if /\b(?:$regex)\b/i;
    }
Run Code Online (Sandbox Code Playgroud)

有关正则表达效率的更多详细信息,请参阅Jeffrey Freidl撰写的I. 他解释了正则表达式引擎如何工作以及为什么某些模式效率低得惊人.一旦了解了perl如何应用正则表达式,您就可以针对各种情况调整它们.


Dav*_*man 10

我一次尝试对多个正则表达式测试一个值是Regexp :: Assemble,它将"将多个正则表达式组装成单个RE",其方式比简单地更加智能和优化join '|', @regexps.默认情况下,您还可以检索匹配的文本部分,如果您需要知道匹配的模式,track交换机将提供该信息.它的性能非常好 - 在一个应用程序中,我用它来同时测试1700个模式 - 我还没有需要它不做的任何事情.