Perl Regex для поиска всех строк, образованных с использованием подстроки

Используя Perl RegEx, как найти самую большую суперстроку в предложении, когда суперстрока является повторением 1 или более подстрок.

Для примера:

$sentence = "zsabcxyzabcabcabccde_xdrabcabcrte__23abcerabcabccbabacxyz";

$subStr = "abc";

Я хочу найти все вхождения abc и самый большой из них.

Выход:

abc

abcabcabc

abcabc

abc

abcabc

Самая большая строка abcabcabc


person Nix    schedule 21.03.2017    source источник
comment
perldoc.perl.org/functions/length.html   -  person mpapec    schedule 21.03.2017


Ответы (4)


Скомпилируйте регулярное выражение, используя квантификатор. + говорит «один или несколько».

Таким образом, ваша «substr» становится ((?:abc)+) внешними скобками для «захвата», внутренние скобки не захватываются. В противном случае вы также получите «частичные» попадания в массив, хотя чистый результат не сильно изменится, потому что самое длинное попадание все равно будет сортироваться вверху.

Например:

#!/usr/bin/env perl

use strict;
use warnings;
use Data::Dumper;

my $sentence = "zsabcxyzabcabcabccde_xdrabcabcrte__23abcerabcabccbabacxyz";
my $substring = "abc";
my $regex = qr/((?:$substring)+)/;
my @matches = $sentence =~ m/$regex/g;

print Dumper \@matches;

#Then sort it:

my ( $longest ) = sort { length ( $b ) <=> length ( $a ) } @matches;

print $longest,"\n";
person Sobrique    schedule 21.03.2017
comment
Может быть необходимо экранировать метасимволы в $substring (quotemeta) - person Håkon Hægland; 21.03.2017

Попробуйте, как показано ниже

use warnings;
use strict;

my $sentence = "zsabcxyzabcabcabccde_xdrabcabcrte__23abcerabcabccbabacxyz";

my ($larg) = sort{length($b)<=>length($a)} $sentence =~ m/((?:abc)+)/g;

print $larg,"\n";

Если не хотите хранить это значит, сделайте цикл

use warnings;
use strict;
my $sentence = "zsabcxyzabcabcabccde_xdrabcabcrte__23abcerabcabccbabacxyzabcabcabcabc";
my $longstr;
my $len = 0;
while($sentence=~m/((?:abc)+)/g)
{
    $longstr = $1 and $len = length($1) if(length($1) > $len)
}

приведенный выше вариант находится в одном регулярном выражении с (?{}), но не рекомендуется

my $sentence = "zsabcxyzabcabcabccde_xdrabcabcrte__23abcerabcabccbabacxyzabcabcabcabc";
my $lar = 0;
my $larg;
$sentence=~m/((?:abc)+)(?{ $larg = $1 and $lar=(length $1) if(length $1 > $lar )}) \G/x;
person mkHun    schedule 21.03.2017

Спасибо @mkHun и @Sobrique... Я использовал @matches = $str =~ m/(abc)+/ng;, а затем сортировал. /n делает его намного проще, я думаю, он доступен с 5.22.

person Nix    schedule 21.03.2017
comment
Не пишите комментарий в качестве ответа. Вы можете поместить это как комментарий под своим вопросом или отредактировать его в своем вопросе. См. Что делать, когда кто-то отвечает на мой вопрос? - person Håkon Hægland; 21.03.2017
comment
это не просто комментарий. Можно рассматривать как другой ответ. - person Nix; 21.03.2017
comment
Хорошо, я пропустил флаг /n. Здорово, что вы нашли это, но все же это может быть опубликовано в качестве комментария, я думаю - person Håkon Hægland; 21.03.2017

Лучший способ следующий: ((?:abc)+) с сортировкой после нахождения совпадений

person RSCh    schedule 21.03.2017