希望用Perl正则表达式替换来重新开始并避免“ 1 while”把戏

时间:2018-11-30 15:07:49

标签: regex perl

示例:我想这样删除$s中的重复字符:

my $s = 'aabbbcbbac';
1 while $s =~ s/((.).*)\2/$1/;
print $s, "\n";                     #prints abc

是否有一种简单快捷的方法来避免1 while的把戏,并仅用一个s///g删除重复项?使它以某种方式“重新开始”?通过使用\G或某种先行式|后看方式?仅添加/g并不是这里的解决方案。

3 个答案:

答案 0 :(得分:8)

这可以通过可变长度的后向查找来完成,这是不允许的。但是可变长度的后向等效于输入相反的方向上的可变长度的前瞻,因此我们可以使用以下技巧:

reverse字符串,使用先行删除字符,然后再次reverse

$t = reverse $s;
$t =~ s/(.)(?=.*\1)//sg;
$s = reverse $t;

如果您具有Perl 5.14或更高版本,并且可以在替换中使用/r修饰符,则会得到

$s = reverse( reverse($s) =~ s/(.)(?=.*\1)//grs );

答案 1 :(得分:5)

可以使用splitgrepjoin以及查找哈希来构建非正则表达式解决方案。不过,它可能不太可读。

my $s = 'aabbbcbbac';
my %seen;
$s = join '', grep { !$seen{$_}++ } split //, $s;
print $s, "\n";

此输出

abc

答案 2 :(得分:1)

否,无法获得as ///来在原始字符串的任何一个位置上匹配两次以上,因为非零宽度匹配将前进到下一个位置,而两个零宽度匹配将前进到下一个位置。不允许同一位置,以免产生无限循环。