Частичное совпадение Perl - PullRequest
       1

Частичное совпадение Perl

3 голосов
/ 02 февраля 2012

Пожалуйста, рассмотрите скрипт ниже, я хочу сопоставить $ b с $ a, даже если $ b - частичное совпадение.Можно ли это сделать?

$a="MCF-7";
$b="MCF";
if($b=~m/$a/i)
{
    print "FOUND";
}

Ответы [ 2 ]

8 голосов
/ 02 февраля 2012

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

Вы, кажется, перепутали $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".

нет совпадений "MCF-7".
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...