2010-05-21 24 views
22

Próbuję przeanalizować pojedynczy ciąg i pobrać wiele fragmentów danych z tego samego ciągu znaków z tymi samymi warunkami wyrażeń regularnych. Ja parsowania pojedynczy dokument HTML, który jest statyczny (za nieujawnioną powodu nie mogę używać parser HTML, aby wykonać zadanie.) Mam wyraz, który wygląda tak:Jak przechwycić wiele dopasowań z tego samego wyrażenia Perl?

$string =~ /\<img\ssrc\="(.*)"/; 

i chcę uzyskać wartość 1 $. Jednak w jednym ciągu istnieje wiele tagów img takich jak to, więc potrzebuję czegoś takiego jak tablica zwrócona (@ 1?) Jest to możliwe?

+0

W takich przypadkach dodaję dodatkowy kontekst do mojego wyrażenia regularnego, aby uzyskać konkretny tag obrazu, który chcę. To znaczy, gdy nie mam ochoty robić tego poprawnie, używając parsera HTML, takiego jak HTML :: SimpleLinkExtor, który wyodrębnia dla ciebie wszystkie wartości img src. –

Odpowiedz

19

Jako odpowiedź Jima, użyj modyfikatora/g (w kontekście listowym lub w pętli).

Ale uwaga na chciwość, nie chcesz, aby .* dopasować więcej niż to konieczne (i nie uciec < =, nie są specjalne).

while($string =~ /<img\s+src="(.*?)"/g) { 
    ... 
} 
+0

Wspaniale, tak, miałem problem z chciwością, to? naprawione. Powiedzmy, czy mógłbyś znać listę znaków, które muszą być usunięte w regex? Zasadniczo uciekam prawie ze wszystkiego, bo nie wiem lepiej: P –

+0

Ogólnie trzeba uciec metaznakom i kwantyfikatorom. W Perlu masz: 'Metaznaki:. $^|() [] \ Kwantyfikatory: * +? {} ' Ale są pewne komplikacje - w szczególności w klasie postaci [] rzeczy się zmieniają. – leonbloy

+1

... ale lepszym sposobem na naprawienie tego problemu z chciwością jest użycie '" ([^ "] *)" '. W wielu silnikach regex będzie to bardziej efektowne, ale, co ważniejsze, jest jaśniejszym stwierdzeniem twoja intencja: chcesz dopasować ", a następnie pewną liczbę * niedwoistych * znaków, po których następują kolejne", a nie dwa "znaki oddzielone najkrótszą możliwą sekwencją * dowolnych znaków *. –

2

Użyj/g modyfikatora i kontekst listy po lewej stronie, tak jak w

@result = $string =~ /\<img\ssrc\="(.*)"/g; 
+0

Ale nie mam tablic ciągów, tylko jeden. Próbuję uzyskać indywidualne źródła z wielu znaczników img w jednym ciągu, zwróconych jako tablica. Próbowałem tego, ale nic nie zwróciło. –

+0

Odpowiedź Roberta podaje poprawną składnię tego podejścia. – leonbloy

+0

Co sądzisz, co robi ten wiążący operator? :) –

5

Wystarczy globalnego modyfikatora/g pod koniec meczu. Następnie pętli aż Nie znaleziono żadnego meczu pozostały

my @matches; 
while ($string =~ /\<img\ssrc\="(.*)"/g) { 
     push(@matches, $1); 
} 
7
@list = ($string =~ m/\<img\ssrc\="(.*)"/g); 

g modyfikator pasuje do wszystkich wystąpień w ciągu. Kontekst list zwraca wszystkie dopasowania. Zobacz operatora m // w perlop.

Powiązane problemy