2009-06-27 5 views
5

Jak używać wyrażeń regularnych Perla w celu wyodrębnienia wszystkich adresów URL określonej domeny (z możliwymi zmiennymi subdomenami) z określonym rozszerzeniem ze zwykłego tekstu? Próbowałem:Używanie wyrażenia regularnego w celu wyodrębnienia adresów URL z tekstu zwykłego za pomocą Perl

my $stuff = 'omg http://fail-o-tron.com/bleh omg omg omg omg omg http://homepage.com/woot.gif dfgdfg http://shomepage.com/woot.gif aaa'; 
while($stuff =~ m/(http\:\/\/.*?homepage.com\/.*?\.gif)/gmsi) 
{ 
print $1."\n"; 
} 

To nie strasznie i daje mi:

http://fail-o-tron.com/bleh omg omg omg omg omg http://homepage.com/woot.gif 
http://shomepage.com/woot.gif 

Myślałem, że nie stałoby się, ponieważ używam .*?, które powinny być non-chciwy i dać mi najmniejszy mecz. Czy ktoś może mi powiedzieć, co robię źle? (Nie chcę jakiś uber-kompleks, konserwy regexp do sprawdzania poprawności adresów URL, chcę wiedzieć, co robię źle, więc mogę uczyć się od niego.)

Odpowiedz

5

Wizyta CPAN: Regexp::Common::URI

Edycja: Nawet jeśli nie chcesz wyrażenia regularnego, możesz przyjrzeć się źródłu testowanego modułu, który działa.

Jeśli chcesz znaleźć adresy URL pasujące do określonego ciągu, możesz z łatwością użyć tego modułu, aby to zrobić.

#!/usr/bin/env perl 
use strict; 
use warnings; 
use Regexp::Common qw/URI/; 

while (<>) { 
    if (m/$RE{URI}{HTTP}{-keep}/) { 
    print $_ if $1 =~ m/what-you-want/; 
    } 
} 
16

URI::Find został specjalnie zaprojektowany w celu rozwiązania tego problemu. Znajdzie wszystkie URI, a następnie możesz je filtrować. Ma kilka heurystyk do obsługi takich rzeczy jak ciągła interpunkcja.

AKTUALIZACJA: Ostatnio zaktualizowany do obsługi Unicode.

0

Myślałem, że to nie powinno się zdarzyć, ponieważ używam. *? które powinny być non-chciwy i dać mi najmniejszy mecz

to robi, ale daje najmniejszą mecz dzieje prawo. Począwszy od pierwszego http i idąc w prawo, jest to najmniejszy mecz.

Należy pamiętać, że w przyszłości nie musisz uciekać z ukośników, ponieważ nie musisz używać ukośników jako separatora. I nie musisz też uciekać z jelita grubego. Następnym razem po prostu to zrobić:

m|(http://.*?homepage.com\/.*?\.gif)| 

lub

m#(http://.*?homepage.com\/.*?\.gif)# 

lub

m<(http://.*?homepage.com\/.*?\.gif)> 

lub jedną z wielu innych znaków można znaleźć w dokumentacji perlre.

1

Adresy URL nie mogą zawierać spacji, dlatego zamiast. *? powinieneś użyć \ S * ?, aby uzyskać zero lub więcej znaków spoza przestrzeni.

+0

[RFC 3986 Dodatek C] (http://tools.ietf.org/html/rfc3986#appendix-C) omawia specjalne problemy związane z wyodrębnianiem URI, w tym przypadki, gdy biała spacja jest dopuszczalna. "W niektórych przypadkach konieczne może być dodanie dodatkowych spacji (spacje, podziały wierszy, tabulatory itp.) W celu rozbicia długiego URI na linie. Białe spacje powinny zostać zignorowane po wyodrębnieniu identyfikatora URI." I "dla niezawodności, oprogramowanie, które akceptuje URI typu użytkownika, powinno próbować rozpoznać i usunąć oba ograniczniki i osadzone białe znaki". To powiedziawszy, z doświadczenia, jest to trudne. – Schwern

0

Oto regex do (miejmy nadzieję) dostać | ekstrakt | uzyskać wszystkie adresy URL z ciągiem | plik tekstowy, który wydaje się działać dla mnie:

m,(http.*?://([^\s)\"](?!ttp:))+),g 

...lub na przykład:

$ echo -e "\n\na blahlah blah:http://www.abc.com/dss.htm?a=1&p=2#chk - blahblah \"https://poi.com/a%20b\"; (http://bbb.comhttp://roch.com/abc) \n" | perl -ne 'while (my $string = <>) { print "$string\n"; while ($string =~ m,(http.*?://([^\s)\"](?!ttp:))+),g) {print "$&\n"} }' 


a blahlah blah:http://www.abc.com/dss.htm?a=1&p=2#chk - blahblah "https://poi.com/a%20b"; (http://bbb.comhttp://roch.com/abc) 

http://www.abc.com/dss.htm?a=1&p=2#chk 
https://poi.com/a%20b 
http://bbb.com 
http://roch.com/abc 

Dla mojego odniesienia noob, tu jest wersja debugowania tego samego polecenia powyżej:

$ echo -e "\n\na blahlah blah:http://www.abc.com/dss.htm?a=1&p=2#chk - blahblah \"https://poi.com/a%20b\"; (http://bbb.comhttp://roch.com/abc) \n" | perl -dne 'use re "debug" ; while (my $string = <>) { print "$string\n"; while ($string =~ m,(http.*?://([^\s)\"](?!ttp:))+),g) {print "$&\n"} }' 

regex mecze na http(s):// - i używa spacji, " i ) jako " exit "znaki; następnie używa positive lookahead, aby na początku spowodować "wyjście" w grupie literowej "http" (jeśli dopasowanie jest już w toku); jednakże, ponieważ to także "zjada" ostatnią postać z poprzedniego meczu, tutaj mecz z wyprzedzeniem przeniesiony zostaje o jeden znak do "ttp:".

Przydatne strony:

Nadzieja pomaga to ktoś,
Pozdrawiam!

EDIT: Ups, właśnie znalazłeś o URI::Find::Simple - search.cpan.org, wydaje się zrobić to samo (poprzez regex - Getting the website title from a link in a string)

2

użyłem następujący kod, aby wyodrębnić linki, które kończy się z konkretnym rozszerzeniem
jak * .htm, * .html, * .gif, * .jpeg. Uwaga: W tym skrypcie rozszerzenie * .html jest napisane najpierw, a następnie * .htm, ponieważ oba mają "htm" wspólnego. Tak więc tego rodzaju zmiany należy wykonywać ostrożnie.

Dane wejściowe: Nazwa pliku zawierająca łącza i nazwę pliku wyjściowego, w którym zostaną zapisane wyniki.
Wyjście: Zostanie zapisane w pliku wyjściowym.

kod idzie tutaj:

use strict; 
use warnings; 

if ($#ARGV != 1) { 
print 
"Incorrect number of arguments.\nArguments: Text_LinkFile, Output_File\n"; 
die $!; 
} 
open FILE_LINKS, $ARGV[0] or die $!; 
open FILE_RESULT, ">$ARGV[1]" or die $!; 

my @Links; 
foreach (<FILE_LINKS>) { 
    my @tempArray; 
    my (@Matches) =($_ =~ m/((https?|ftp):\/\/[^\s]+\.(html?|gif|jpe?g))/g); 
    for (my $i = 0 ; $i < $#Matches ; $i += 3) { 
     push(@Links, $Matches[$i]); 
     } 
    } 
print FILE_RESULT join("\n", @Links); 

Wyjście z Twojego ciąg jest tutaj:

http://homepage.com/woot.gif 
http://shomepage.com/woot.gif 
+0

Dlaczego nie używasz '(html? | Gif | jpe? G)' zamiast '(html | htm | gif | jpeg | jpg)'? –

+0

@BradGilbert: tak, to jest lepsze :) – Pushpendra

+0

Idealnie, idealnie! –

1
https?\:\/\/[^\s]+[\/\w] 

Ten regex pracował dla mnie

+0

Byłoby trochę więcej kontekstu i/lub wyjaśnienia byłoby miło. –

Powiązane problemy