Сопоставление последовательных символов из строки с помощью регулярного выражения - PullRequest
3 голосов
/ 17 января 2020

Я не уверен, как озаглавить этот вопрос, поэтому двигаясь дальше ...

Я бы хотел иметь возможность сопоставить часть строки, которая является подмножеством большей строки. Например:

  • MatchPartOfThisString -> Справочная строка
  • fThisDiff -> строка Я бы хотел, чтобы совпадения соответствовали 5 последовательным символам в

Я полагаю, что мог бы пройти l oop через первую строку, взяв минимальное количество последовательных совпадений из ссылочной строки, и посмотреть, совпадает ли другая строка с каждым из совпадений, которые я получаю при систематической попытке сопоставления:

if(fThisDiff =~ /Match/) {
    do something...;
}
if(fThisDiff =~ /atchP/) {
    do something...;
}
if(fThisDiff =~ /tchPa/) {
    do something...;
}

et c.

Я хотел бы сделать это более элегантно, хотя, если есть способ неоднократно интерпретировать части контрольной строки с помощью единственного регулярного выражения. Я не думаю, что это так, но я бы хотел получить подтверждение независимо от этого.

Ответы [ 3 ]

4 голосов
/ 18 января 2020

Вот основа c, сделанная вручную с помощью встроенных инструментов.

Создание шаблона регулярного выражения с чередованием подстрок желаемой длины из вашей ссылочной строки.

use warnings;
use strict;
use feature 'say';

sub get_alt_re {
    my ($str, $len) = @_; 
    $len //= 1;            #/
    my @substrings;
    foreach my $beg (0 .. length($str)-$len) {
        push @substrings, substr($str, $beg, $len);
    }
    return '(' .  join('|', map quotemeta, @substrings) . ')';
}   

my $ref    = q(MatchPartOfThisString);
my $target = q(fThisDiff);

my $re = get_alt_re($ref, 5);

my @m = $target =~ /$re/g;
say for @m; 

Печатает строку fThis.

Код должен быть сделан более крепкий и общий. Затем его довольно легко изменить, чтобы он соответствовал диапазону длин (не только одному, 5 выше). Кроме того, он может использовать библиотеки для подзадач (эти повторные вызовы substr просят код C). Но это показывает, что базовое решение c может быть довольно простым.

3 голосов
/ 18 января 2020

Наилучшим подходом было бы использование алгоритма самая длинная общая подстрока (не путать с алгоритмом самая длинная общая подпоследовательность с таким же именем), а затем проверка его длины.

use String::LCSS_XS qw( lcss );

my $longest = lcss("MatchPartOfThisString", "fThisDiff");
say length($longest);

Если у вас действительно длинные строки, и вы хотите выжимать каждую миллисекунду, адаптированная версия алгоритма, которая завершается, как только будет найдена целевая длина, и которая избегает построения строки, будет быстрее.

3 голосов
/ 18 января 2020

Нет простого способа сделать это с помощью функций регулярных выражений, но пара модулей CPAN может помочь в создании такого регулярного выражения в этом случае.

use strict;
use warnings;
use String::Substrings 'substrings';
use Data::Munge 'list2re';

my $match_string = 'MatchPartOfThisString';
my $re = list2re substrings $match_string, 5;
my $subject = 'fThisDiff';
if ($subject =~ m/($re)/) {
  print "Matched $1 from $match_string in $subject\n";
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...