如何匹配两个值,使其独立于字符串中各自的位置

时间:2010-12-14 15:26:10

标签: regex perl

我正在寻找同时匹配两个值的最佳方法。

如果两个值都在字符串中但我不知道它们出现在字符串中的顺序(例如abcdefbedfa以防我想要的话,我想得到一个真值匹配ab

是否有更好的解决方案(特别是如果以后我需要更复杂的值来匹配),而不是:

$string =~ m/(a.*b)|(b.*a)/i

4 个答案:

答案 0 :(得分:11)

$string =~ /a/i && $string =~ /b/i;

答案 1 :(得分:5)

您可以使用正向前瞻:

$string =~ /^(?=.*a)(?=.*b).*$/i

一般情况下,如果您想检查字符串中任何位置是否存在foobar

$string =~ /^(?=.*foo)(?=.*bar).*$/i

如果您希望将foobar作为单独的单词而不是任何其他单词的子字符串,则可以将单词边界添加为:

$string =~ /^(?=.*\bfoo\b)(?=.*\bbar\b).*$/i

稍后如果您想添加baz存在的检查,您可以这样做:

$string =~ /^(?=.*\bfoo\b)(?=.*\bbar\b)(?=.*\bbaz\b).*$/i

答案 2 :(得分:3)

从我的评论中扩展起来是对所提出的一些解决方案的比较。

#!/usr/bin/perl

use strict;
use warnings;
use Benchmark qw(cmpthese);

my $two_regexp = q{
    for my $string ('This and that', 'Not that, this!', 'do not match this') {
        if ($string =~ /this/i && $string =~ /that/i) {
            1;
        }
    }
};

my $alternation = q{
    for my $string ('This and that', 'Not that, this!', 'do not match this') {
        if ($string =~ m/(this.*that)|(that.*this)/i) {
            1;
        }
    }
};

my $alternation_no_capture = q{
    for my $string ('This and that', 'Not that, this!', 'do not match this') {
        if ($string =~ m/(?:this.*that)|(?:that.*this)/i) {
            1;
        }
    }
};

my $anchored_lookahead = q{
    for my $string ('This and that', 'Not that, this!', 'do not match this') {
        if ($string =~ /^(?=.*this)(?=.*that).*$/i) {
            1;
        }
    }
};

my $start_anchored_lookahead = q{
    for my $string ('This and that', 'Not that, this!', 'do not match this') {
        if ($string =~ /^(?=.*this)(?=.*that)/i) {
            1;
        }
    }
};

my $free_lookahead = q{
    for my $string ('This and that', 'Not that, this!', 'do not match this') {
        if ($string =~ /(?=.*this)(?=.*that)/i) {
            1;
        }
    }
};

cmpthese(-1, {
    two_regexp               => $two_regexp,
    alternation              => $alternation,
    alternation_no_capture   => $alternation_no_capture,
    anchored_lookahead       => $anchored_lookahead,
    start_anchored_lookahead => $start_anchored_lookahead,
    free_lookahead           => $free_lookahead,
});

您应该使用实际模式和一组实际数据来运行它,它可以从根本上改变结果。最新版本的Perl具有更改正则表达式性能,因此我的结果可能与您的结果不太接近。在Perl 5.8.8盒子上,我得到了这些结果。

                             Rate free_lookahead alternation alternation_no_capture anchored_lookahead start_anchored_lookahead two_regexp
free_lookahead           170836/s             --        -55%                   -61%               -61%                     -67%       -73%
alternation              378300/s           121%          --                   -13%               -13%                     -27%       -40%
alternation_no_capture   432784/s           153%         14%                     --                -1%                     -17%       -31%
anchored_lookahead       436906/s           156%         15%                     1%                 --                     -16%       -30%
start_anchored_lookahead 518950/s           204%         37%                    20%                19%                       --       -17%
two_regexp               628278/s           268%         66%                    45%                44%                      21%         --

因此,至少我的审美意识和使用两场比赛的Perl版本双赢。

答案 3 :(得分:1)

为什么不呢?

$string =~ /a/i && $string =~ /b/i

它更清晰。