我需要编写一个接收字符串和正则表达式的函数。我需要检查是否有匹配并返回匹配的开始和结束位置。 (正则表达式已由qr//
编译。)
该函数也可能会收到一个“全局”标志,然后我需要返回所有匹配的(开始,结束)对。
我无法更改正则表达式,甚至不会在其周围添加()
,因为用户可能会使用()
和\1
。也许我可以使用(?:)
。
示例:给出“ababab”和正则表达式qr/ab/
,在全局情况下,我需要返回3对(开始,结束)。
答案 0 :(得分:72)
内置变量@-
和@+
分别保存上次成功匹配的开始和结束位置。 $-[0]
和$+[0]
对应于整个模式,而$-[N]
和$+[N]
对应$N
($1
,$2
等。)submatches。
答案 1 :(得分:19)
忘记我以前的帖子,我有一个更好的主意。
sub match_positions {
my ($regex, $string) = @_;
return if not $string =~ /$regex/;
return ($-[0], $+[0]);
}
sub match_all_positions {
my ($regex, $string) = @_;
my @ret;
while ($string =~ /$regex/g) {
push @ret, [ $-[0], $+[0] ];
}
return @ret
}
这种技术不会以任何方式改变正则表达式。
编辑添加:引用来自 perlvar 的$ 1 .. $ 9。 “这些变量都是只读的,并且动态地限定为当前的BLOCK。”换句话说,如果你想使用$ 1 .. $ 9,你就不能使用子程序进行匹配。
答案 2 :(得分:10)
pos函数为您提供匹配的位置。如果将正则表达式放在括号中,则可以使用length $1
获取长度(从而得到结束)。喜欢这个
sub match_positions {
my ($regex, $string) = @_;
return if not $string =~ /($regex)/;
return (pos($string), pos($string) + length $1);
}
sub all_match_positions {
my ($regex, $string) = @_;
my @ret;
while ($string =~ /($regex)/g) {
push @ret, [pos($string), pos($string) + length $1];
}
return @ret
}
答案 3 :(得分:0)
如果您愿意让程序中的所有RE执行得更慢,您也可以使用弃用的$`变量。来自perlvar:
$‘ The string preceding whatever was matched by the last successful pattern match (not
counting any matches hidden within a BLOCK or eval enclosed by the current BLOCK).
(Mnemonic: "`" often precedes a quoted string.) This variable is read-only.
The use of this variable anywhere in a program imposes a considerable performance penalty
on all regular expression matches. See "BUGS".
答案 4 :(得分:0)
#!/usr/bin/perl
# search the postions for the CpGs in human genome
sub match_positions {
my ($regex, $string) = @_;
return if not $string =~ /($regex)/;
return (pos($string), pos($string) + length $1);
}
sub all_match_positions {
my ($regex, $string) = @_;
my @ret;
while ($string =~ /($regex)/g) {
push @ret, [(pos($string)-length $1),pos($string)-1];
}
return @ret
}
my $regex='CG';
my $string="ACGACGCGCGCG";
my $cgap=3;
my @pos=all_match_positions($regex,$string);
my @hgcg;
foreach my $pos(@pos){
push @hgcg,@$pos[1];
}
foreach my $i(0..($#hgcg-$cgap+1)){
my $len=$hgcg[$i+$cgap-1]-$hgcg[$i]+2;
print "$len\n";
}