Regex Perl拆分函数-使用重复字符作为分隔符
我想使用重复字母作为分隔符拆分字符串,例如,Regex Perl拆分函数-使用重复字符作为分隔符,regex,perl,Regex,Perl,我想使用重复字母作为分隔符拆分字符串,例如, “123aa23a3”应拆分为('123',23a3'),而“123abc4”应保持不变。 所以我试了一下: @s = split /([[:alpha:]])\1+/, '123aaaa23a3'; 但这返回的是'123','a','23a3',这不是我想要的。现在我知道这是因为,'aaaa'中的最后一个'a'被偏执狂捕获,并因此被split()保存。但无论如何,我不能添加像?:这样的内容,因为必须捕获[[:alpha:]以供反向引用。 我怎样才
“123aa23a3”
应拆分为('123',23a3')
,而“123abc4”
应保持不变。所以我试了一下:
@s = split /([[:alpha:]])\1+/, '123aaaa23a3';
但这返回的是'123','a','23a3'
,这不是我想要的。现在我知道这是因为,'aaaa'
中的最后一个'a'
被偏执狂捕获,并因此被split()
保存。但无论如何,我不能添加像?:
这样的内容,因为必须捕获[[:alpha:]
以供反向引用。
我怎样才能解决这个问题呢?嗯,这是一个有趣的问题。我的第一个想法是-您的分隔符将始终是奇数,因此您可以丢弃任何奇数数组元素 也许是这样的
my %s = (split (/([[:alpha:]])\1+/, '123aaaa23a3'), '' );
print Dumper \%s;
这将为您提供:
$VAR1 = {
'23a3' => '',
'123' => 'a'
};
因此,您可以通过键
提取模式
不幸的是,我通过%+
选择模式匹配的第二种方法没有特别的帮助(split没有填充regex内容)
但是像这样的事情:
my @delims ='123aaaa23a3' =~ m/(?<delim>[[:alpha:]])\g{delim}+/g;
print Dumper \%+;
我们首先处理字符串以提取“2个或更多”字符模式,将其设置为Delmiter。然后,我们用非捕获的方法将它们组合成一个正则表达式,这样我们就可以拆分了 一种解决方案是使用原始的
split
调用并丢弃所有其他值。方便的是,List::Util::pairkeys
是一个将每对值中的第一个保留在其输入列表中的函数:
use List::Util 1.29 qw( pairkeys );
my @vals = pairkeys split /([[:alpha:]])\1+/, '123aaaa23a3';
给予
这个警告来自这样一个事实,pairkeys
想要一个大小相等的列表。我们可以通过在末尾增加一个值来解决这个问题:
my @vals = pairkeys split( /([[:alpha:]])\1+/, '123aaaa23a3' ), undef;
或者,也许更简洁一点,就是在列表的开头添加额外的值,并使用pairvalues
:
use List::Util 1.29 qw( pairvalues );
my @vals = pairvalues undef, split /([[:alpha:]])\1+/, '123aaaa23a3';
在正则表达式中,可以使用延迟执行断言(也称为延迟正则子表达式),
(?{code})
,使“拆分”直接工作:
@s = split /[[:alpha:]](??{"$&+"})/, '123aaaa23a3';
(?{code})
记录在“perlre”手册页面上
请注意,根据“perlvar”手册页面,在程序中的任何位置使用
$&
都会对所有正则表达式匹配造成相当大的性能损失。我从来没有发现这是一个问题,但是YMMV。我不认为您可以修改正则表达式以避免创建捕获组,但是您可以扔掉split
返回的列表中所有奇数元素。如果正则表达式有捕获组,则返回的列表也包含匹配/分组的子字符串。您可以使用另一个选项:my$str='123aaaa23a3'=~s/([[:alpha:]])\1+/~/r;my@s=split/~~/,$str代码>
use List::Util 1.29 qw( pairvalues );
my @vals = pairvalues undef, split /([[:alpha:]])\1+/, '123aaaa23a3';
@s = split /[[:alpha:]](??{"$&+"})/, '123aaaa23a3';