示例:我想这样删除$s
中的重复字符:
my $s = 'aabbbcbbac';
1 while $s =~ s/((.).*)\2/$1/;
print $s, "\n"; #prints abc
是否有一种简单快捷的方法来避免1 while
的把戏,并仅用一个s///g
删除重复项?使它以某种方式“重新开始”?通过使用\G
或某种先行式|后看方式?仅添加/g
并不是这里的解决方案。
答案 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)
可以使用split
,grep
和join
以及查找哈希来构建非正则表达式解决方案。不过,它可能不太可读。
my $s = 'aabbbcbbac';
my %seen;
$s = join '', grep { !$seen{$_}++ } split //, $s;
print $s, "\n";
此输出
abc
答案 2 :(得分:1)
否,无法获得as ///来在原始字符串的任何一个位置上匹配两次以上,因为非零宽度匹配将前进到下一个位置,而两个零宽度匹配将前进到下一个位置。不允许同一位置,以免产生无限循环。