Хотя регулярные выражения могут сделать это, похоже, что вашу проблему также можно решить с помощью функции 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
}