it-swarm-id.com

Bagaimana saya bisa menemukan lokasi kecocokan regex di Perl?

Saya perlu menulis fungsi yang menerima string dan regex. Saya perlu memeriksa apakah ada pertandingan dan mengembalikan lokasi awal dan akhir pertandingan. (Regex sudah dikompilasi oleh qr//.)

Fungsi ini mungkin juga menerima bendera "global" dan kemudian saya harus mengembalikan pasangan (mulai, akhir) semua pertandingan.

Saya tidak dapat mengubah regex, bahkan tidak menambahkan () di sekitarnya karena pengguna mungkin menggunakan () dan \1. Mungkin saya bisa menggunakan (?:).

Contoh: diberi "ababab" dan regex qr/ab/, dalam kasus global saya harus mendapatkan kembali 3 pasang (mulai, akhir).

32
szabgab

Variabel bawaan @- dan @+ masing-masing memegang posisi awal dan akhir, dari pertandingan yang berhasil terakhir. $-[0] dan $+[0] sesuai dengan seluruh pola, sedangkan $-[N] dan $+[N] sesuai dengan $N ($1, $2, dll.).

72
Michael Carman

Lupakan posting saya sebelumnya, saya punya ide yang lebih baik.

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
}

Teknik ini tidak mengubah regex dengan cara apa pun.

Diedit untuk menambahkan: untuk mengutip dari perlvar pada $ 1 .. $ 9. "Variabel-variabel ini semua read-only dan secara dinamis mencakup untuk BLOCK saat ini." Dengan kata lain, jika Anda ingin menggunakan $ 1 .. $ 9, Anda tidak dapat menggunakan subrutin untuk melakukan pencocokan.

19
Leon Timmermans

Fungsi pos memberi Anda posisi pertandingan. Jika Anda memasukkan regex Anda dalam tanda kurung Anda bisa mendapatkan panjangnya (dan akhirnya) menggunakan length $1 Seperti ini

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

Anda juga dapat menggunakan variabel $ `yang sudah tidak digunakan lagi, jika Anda mau semua RE di program Anda berjalan lebih lambat. Dari 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".
0
zigdon