2011-09-11 34 views
5

Bir metin dosyasında "CCGTCAATTC (A | C) TTT (A | G) AGT" oluşumu arıyorum.Dizin işlevinde düzenli ifade

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

Arıyor çalışıyor ama doğrultusunda "metin" konumunu elde edebilir değilim. Dizin, normal bir ifadeyi alt dizgi olarak kabul etmiyor gibi görünüyor.

Bu işi nasıl yapabilirim? Teşekkürler

cevap

13

@- dizisi, son başarılı eşleşmenin başlangıç ​​konumlarının ofsetlerini tutar. İlk eleman tüm eşleşen modelin ofsetidir ve sonraki elemanlar parantezize edilmiş alt-desenlerin ofsetidir. Yani, bir eşleşme olduğunu biliyorsanız, ofsetini $-[0] olarak alabilirsiniz.

1

index'u kullanmanız gerekmez, sadece bir regex. Regex eşlemenizden önce gelen $line bölümü, $` (veya İngilizce'yi kullanmayı seçtiyseniz $PREMATCH) 'da saklanır. Sen $` uzunluğunu kontrol ederek maçın endeksi alabilirsiniz ve size $& (veya $MATCH) değişkeninden maçı kendisi alabilirsiniz: Kalan eşleşen devam etmek $pos almak istiyorum varsayarsak

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

$line bölümünün bir parçası olan $' (veya $POSTMATCH) değişkenini, eşlemeden sonra gelen $line kısmını almak için kullanabilirsiniz.

Bu özel değişkenler hakkında ayrıntılı bilgi için bkz http://perldoc.perl.org/perlvar.html.

+0

Evet, yapabilirim. Ama pozisyonu bir kez yakaladığımda, sonraki 50 karaktere sahip olmak istiyorum: 'substr ($ line, $ pos, 50)' – Deep

+0

$ çizgisinin kalan kısmına denk gelebilirsin - bu yaklaşım, bir sebep mi var? $ '(Veya $ POSTMATCH) değişkenini, $ line'ın kalan kısmını kolayca almak için de kullanabilirsiniz. –

+0

Lütfen değiştirilmiş cevabımı inceleyin; Başka bir şey arıyorsanız bana bildirin. –

1

Yorumlarınıza dayanarak, yaptığınız maçın hemen ardından 50 karakterle eşleşiyor gibi görünüyor. Yani, basit bir çözüm olacaktır:

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

Gördüğünüz gibi, [AG]A|G eşdeğerdir. Birden çok kez eşleştirmek isterseniz, @matches dizisini ve normal ifadede /g genel seçeneğini kullanabilirsiniz. Örneğin.

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

Sen eşleştirme kalıbını tutmak için bunu yapabilirsiniz:

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

Ya bir döngü içinde:

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

Aslında eşleşen karakter o kadar hile zorunda edilebilir ve yerine 50 38 – Deep

+0

soru için bir sürü basit olmazdı koymak gerek istediğini almak mümkün Baştan ne istediğini söylesen cevap ver. =) Peki, kaç karakterin yakalanmasını istediğinizi bildiğinizi varsayarsak, bunu nasıl düzelteceğinizi öğrenebilirsiniz. TLP – TLP

+0

Bu aynı zamanda, bana başka fikir verdi – Deep

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

Hoşuma fakat while hiçbir ;.

Hataların nedenini bulmakta zor zamanlar geçirdim. T_T.