Пожалуйста, рассмотрите сценарий ниже, я хочу, чтобы соответствовать $ b до $ a, даже если $ b является частичным совпадением. Можно ли это сделать?Perl частичное совпадение
$a="MCF-7";
$b="MCF";
if($b=~m/$a/i)
{
print "FOUND";
}
Пожалуйста, рассмотрите сценарий ниже, я хочу, чтобы соответствовать $ b до $ a, даже если $ b является частичным совпадением. Можно ли это сделать?Perl частичное совпадение
$a="MCF-7";
$b="MCF";
if($b=~m/$a/i)
{
print "FOUND";
}
Хотя регулярные выражения могут сделать это, это звучит как ваша проблема также может быть решена с помощью функции index
:
say index($haystack, $needle) >= 0 ? 'match' : 'fail'; # any position
say index($haystack, $needle) == 0 ? 'match' : 'fail'; # anchored at start
index
функция чувствительна к регистру. Если вы хотите нечувствительное соответствие, примените функцию uc
или lc
к обоим аргументам.
Хотя функция index
будет намного быстрее, чем регулярное выражение, если вы хотите использовать регулярное выражение, вы можете создать генератор регулярных выражений, который производит череду чередования, которые будут выполнять частичное совпадение.
sub build_partial {
my ($str, $min) = (@_, 1);
my @re;
for (0 .. length($str) - $min) {
my $str = substr $str, $_;
for ($min .. length $str) {
push @re, quotemeta substr $str, 0, $_
}
}
my $re = join '|' => sort {length $a <=> length $b} @re;
qr/^(?:$re)$/i
}
my $haystack = 'MCF-7';
my $needle = 'MCF';
my $regex = build_partial $haystack;
say $needle =~ /$regex/ ? 'match' : 'fail'; # match
Регулярное выражение Генерация MCF-7
выглядит следующим образом:
/^(?:M|C|F|7|MC|CF|\-|MCF|F\-|\-7|CF\-|F\-7|MCF\-|CF\-7|MCF\-7)$/i
И это будет соответствовать, даже если игла один символ из стога. build_partial
принимает необязательный номер, указывающий на минимальную длину, необходимую для матча:
my $regex_3 = build_partial $haystack, 3;
который производит это регулярное выражение:
/^(?:MCF|CF\-|F\-7|MCF\-|CF\-7|MCF\-7)$/i
Эти модели соответствовать подстроку, начиная с любой позиции. Если вы хотите, чтобы он был привязан к передней части струны, build_partial
становится немного проще:
sub build_partial {
my ($str, $min) = (@_, 1);
my $re = join '|' => map {
quotemeta substr $str, 0, $_
} $min .. length $str;
qr/^(?:$re)$/i
}
Мне нравится подход, хотя мне интересно, почему вы используете 'join '|' => 'вместо' join '|' '. – flesk
@flesk => только личное предпочтение кодирования. Я склонен использовать жирную стрелу в любое время, когда она привлекает полезную связь между аргументами. поэтому 'join '' => @ list', но не' push @array => @ list', так как это обратное –
Вы, кажется, $a
и $b
смешались:
use strict;
use warnings;
my $a="MCF-7";
my $b="MCF";
if($a=~/$b/i) #tests for case-insensitive matching of $b within $a.
{
print "Found\n";
}
код в вашем вопросе не произвел никакого вывода, так как нет матча "MCF-7"
в "MCF"
.
Не можете ли вы просто изменить смысл? 'print" FOUND ", если $ a = ~/$ b/i;'? – unpythonic