使用正则表达式匹配字符串中的连续字符

时间:2020-01-17 20:59:37

标签: regex perl

我不确定如何为这个问题加上标题,所以继续...

我希望能够匹配作为较大字符串子集的一部分字符串。例如:

  • MatchPartOfThisString->参考字符串
  • fThisDiff->字符串,我想说匹配5个连续的字符

我想我可以遍历第一个字符串,从参考字符串中获取最少的连续匹配项,然后看看其他字符串是否与我从系统地尝试匹配得到的每个匹配项中匹配:

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

但是,如果有一种方法可以使用奇异的正则表达式重复解释引用字符串的某些部分,则我想做得更优雅。我认为情况并非如此,但是无论如何我都希望得到确认。

3 个答案:

答案 0 :(得分:4)

这是内置工具手工完成的基本操作。

使用参考字符串与所需长度的子字符串交替构建正则表达式模式。

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

应该使代码更健壮和通用。然后,可以很容易地对其进行修改以匹配一定范围的长度(不仅是上面的一个,还有五个)。此外,它可以将库用于子任务(那些对substr的重复调用乞求C代码)。但这表明基本的解决方案可能非常简单。

答案 1 :(得分:3)

使用正则表达式功能没有简单的方法,但是在这种情况下,几个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";
}

答案 2 :(得分:3)

最好的方法是使用longest common substring算法(不要与类似命名的longest common subsequence算法混淆),然后检查其长度。

use String::LCSS_XS qw( lcss );

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

如果您的字符串真的很长,并且希望每毫秒压缩一次,则该算法的定制版本会在找到目标长度后立即退出,并且避免构建字符串会更快。