我正在寻找同时匹配两个值的最佳方法。
如果两个值都在字符串中但我不知道它们出现在字符串中的顺序(例如abcdef
或bedfa
以防我想要的话,我想得到一个真值匹配a
和b
)
是否有更好的解决方案(特别是如果以后我需要更复杂的值来匹配),而不是:
$string =~ m/(a.*b)|(b.*a)/i
答案 0 :(得分:11)
$string =~ /a/i && $string =~ /b/i;
答案 1 :(得分:5)
您可以使用正向前瞻:
$string =~ /^(?=.*a)(?=.*b).*$/i
一般情况下,如果您想检查字符串中任何位置是否存在foo
和bar
:
$string =~ /^(?=.*foo)(?=.*bar).*$/i
如果您希望将foo
和bar
作为单独的单词而不是任何其他单词的子字符串,则可以将单词边界添加为:
$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
它更清晰。