it-swarm-tr.com

Bir regex eşleşmesinin Perl'deki yerini nasıl bulabilirim?

Bir dize ve bir regex alan bir işlev yazmam gerekiyor. Bir eşleşme olup olmadığını kontrol etmem ve eşleşmenin başlangıç ​​ve bitiş konumunu döndürmem gerekir. (Düzenli ifade zaten qr// tarafından derlendi.)

İşlev ayrıca "global" bayrağı da alabilir ve tüm eşleşmelerin (başlangıç, bitiş) çiftlerini döndürmem gerekir.

Regex'i değiştiremiyorum, kullanıcı () ve () kullanabileceği için etrafına \1 bile eklemiyorum. Belki (?:) kullanabilirim.

Örnek: "ababab" ve regex qr/ab/ ifadesi verildiğinde, genel durumda 3 çift geri almam gerekiyor (başlangıç, bitiş).

32
szabgab

Dahili değişkenler @- ve @+, son başarılı karşılaşmanın sırasıyla başlangıç ​​ve bitiş konumlarını tutar. $-[0] ve $+[0] tüm desene karşılık gelirken, $-[N] ve $+[N]$N ($1, $2, vb.) alt eşleşmelerine karşılık gelir.

72
Michael Carman

Önceki yazımı unut, daha iyi bir fikrim var.

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
}

Bu teknik, regex'i hiçbir şekilde değiştirmez.

Eklemek için düzenlendi: perlvar dan 1 $ 'a teklif vermek için. "Bu değişkenlerin tümü salt okunur ve dinamik olarak geçerli BLOCK'a dahil edildi." Başka bir deyişle, $ 1 .. $ 9 kullanmak istiyorsanız, eşleştirmeyi yapmak için bir alt yordam kullanamazsınız.

19
Leon Timmermans

Pos fonksiyonu size eşleşmenin konumunu verir. Eğer regex'inizi parantez içine alırsanız, length $1 kullanarak uzunluğu (ve böylece sonunu) alabilirsiniz. Bunun gibi

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
}
10
Leon Timmermans
#!/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
Shicheng Guo

Programınızdaki tüm RE'lerin daha yavaş çalışmasını istiyorsanız, kullanımdan kaldırılan $ `değişkenini de kullanabilirsiniz. Perlvar'dan:

   $‘      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".
0
zigdon