2011-09-11 14 views
5

Szukam wystąpienia "CCGTCAATTC (A | C) TTT (A | G) AGT" w pliku tekstowym.Wyrażenie regularne w funkcji indeksu

$text = 'CCGTCAATTC(A|C)TTT(A|G)AGT'; if ($line=~/$text/){ chomp($line); $pos=index($line,$text); }

Wyszukany działa, ale nie jestem w stanie uzyskać pozycję „tekst” w kolejce. Wygląda na to, że indeks nie akceptuje wyrażeń regularnych jako podciągów.

Jak mogę to ułatwić? Dzięki

Odpowiedz

13

Macierz @- przechowuje przesunięcia pozycji wyjściowych ostatniego udanego meczu. Pierwszym elementem jest przesunięcie całego pasującego wzorca, a kolejne elementy są przesunięciami nawiasów podrzędnych. Tak więc, jeśli wiesz, że było dopasowanie, możesz uzyskać jego offset jako $-[0].

1

W ogóle nie trzeba używać index, tylko wyrażenie regularne. Część numeru $line, która pojawi się przed twoim dopasowaniem do wyrażenia regularnego, będzie przechowywana w $` (lub $PREMATCH, jeśli zdecydujesz się użyć angielskiego;). Można uzyskać indeks meczu sprawdzając długość $` i można dostać sam mecz z $& (lub $MATCH) Zmienna:

$text = 'CCGTCAATTC(A|C)TTT(A|G)AGT'; 
if ($line =~ /$text/) { 
    $pos = length($PREMATCH); 
} 

Zakładając chcesz dostać $pos kontynuować dopasowanie na pozostałe część $line, możesz użyć zmiennej $' (lub $POSTMATCH), aby pobrać część $line, która pojawi się po zakończeniu meczu.

Aby uzyskać szczegółowe informacje na temat tych zmiennych specjalnych, patrz: http://perldoc.perl.org/perlvar.html.

+0

Tak, mogę to zrobić. Ale gdy zdobędę pozycję, to mam przechwycić następne 50 znaków: 'substr ($ line, $ pos, 50)' – Deep

+0

Możesz dopasować pozostałą część linii $ tak jak powiedziałeś - jest to podejście niepożądane dla jakiś powód? Możesz także użyć zmiennej $ '(lub $ POSTMATCH), aby łatwo uzyskać pozostałą część linii $. –

+0

Proszę zobaczyć moją poprawioną odpowiedź; daj mi znać, jeśli szukasz czegoś innego. –

1

Na podstawie Twoich komentarzy wygląda na to, że to, czego szukasz, pasuje do 50 znaków bezpośrednio po zakończeniu meczu. Tak, to proste rozwiązanie byłoby:

my ($match) = $line =~ /CCGTCAATTC[AC]TTT[AG]AGT(.{50})/; 

Jak widać, [AG] jest równoważna A|G. Jeśli chcesz dopasować wiele razy, możesz użyć tablicy globalnej @matches i globalnej opcji /g w regex. Na przykład.

my @matches = $line =~ /CCGTCAATTC[AC]TTT[AG]AGT(.{50})/g; 

Można to zrobić, aby zachować wzór pasujący:

my ($pattern, $match) = $line =~ /(CCGTCAATTC[AC]TTT[AG]AGT)(.{50})/g; 

Albo w pętli:

while ($line =~ /(CCGTCAATTC[AC]TTT[AG]AGT)(.{50})/g;) { 
    my ($pattern, $match) = ($1, $2); 
} 
+0

Właściwie, potrzebuję pasujących znaków, więc być może trzeba oszukiwać, a zamiast 50 umieścić 38 – Deep

+0

Czy twoje pytanie nie byłoby o wiele prostsze odpowiedź, jeśli od początku mówiłeś, czego chciałeś? =) Cóż, zakładając, że wiesz, ile znaków chcesz przechwycić, myślę, że możesz się dowiedzieć, jak to naprawić. – TLP

+0

To także dało mi inny pomysł, tak, że TLP – Deep

0
while ($line =~ /(CCGTCAATTC[AC]TTT[AG]AGT)(.{50})/g;) { 

mi się podoba, ale nie ; w while.

Miałem ciężkie czasy na poszukiwanie przyczyny błędów. T_T.