Как я могу найти местоположение соответствия регулярному выражению в Perl? - PullRequest
32 голосов
/ 18 сентября 2008

Мне нужно написать функцию, которая получает строку и регулярное выражение. Мне нужно проверить, есть ли совпадение и вернуть начальное и конечное местоположение совпадения. (Регулярное выражение уже составлено qr//.)

Функция также может получить «глобальный» флаг, а затем мне нужно вернуть пары (начало, конец) всех совпадений.

Я не могу изменить регулярное выражение, даже не добавив () вокруг него, так как пользователь может использовать () и \1. Может быть, я могу использовать (?:).

Пример: учитывая "ababab" и регулярное выражение qr/ab/, в глобальном случае мне нужно вернуть 3 пары (начало, конец).

Ответы [ 5 ]

72 голосов
/ 18 сентября 2008

Встроенные переменные @- и @+ содержат соответственно начальную и конечную позиции последнего успешного совпадения. $-[0] и $+[0] соответствуют всему шаблону, а $-[N] и $+[N] соответствуют субматчам $N ($1, $2 и т. Д.).

19 голосов
/ 18 сентября 2008

Забудьте мой предыдущий пост, у меня есть идея получше.

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, вы не можете использовать подпрограмму для сопоставления.

10 голосов
/ 18 сентября 2008

Функция 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
}
0 голосов
/ 22 января 2016
#!/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"; 
}
0 голосов
/ 18 сентября 2008

Вы также можете использовать устаревшую переменную $ `, если вы хотите, чтобы все 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".
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...