Ответ 1
Встроенные переменные @-
и @+
сохраняют начальную и конечную позиции, соответственно, последнего успешного совпадения. $-[0]
и $+[0]
соответствуют всей схеме, а $-[N]
и $+[N]
соответствуют подматрицам $N
($1
, $2
и т.д.).
Мне нужно написать функцию, которая получает строку и регулярное выражение. Мне нужно проверить, есть ли совпадение и вернуть начальное и конечное местоположение совпадения. (Регулярное выражение уже скомпилировано qr//
.)
Функция может также получить флаг "global", а затем мне нужно вернуть пары (начало, конец) всех совпадений.
Я не могу изменить регулярное выражение, даже не добавить ()
вокруг него, так как пользователь может использовать ()
и \1
. Может быть, я могу использовать (?:)
.
Пример: с учетом "ababab" и регулярного выражения qr/ab/
, в глобальном случае мне нужно вернуть 3 пары (начало, конец).
Встроенные переменные @-
и @+
сохраняют начальную и конечную позиции, соответственно, последнего успешного совпадения. $-[0]
и $+[0]
соответствуют всей схеме, а $-[N]
и $+[N]
соответствуют подматрицам $N
($1
, $2
и т.д.).
Забыть мой предыдущий пост, у меня есть лучшая идея.
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. "Эти переменные доступны только для чтения и динамически привязаны к текущему блоку.. Другими словами, если вы хотите использовать $1.. $9, вы не можете использовать подпрограмму для выполнения сопоставления.
Функция 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
}
Вы также можете использовать устаревшую переменную $`, если вы хотите, чтобы все 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".
#!/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";
}