Использование регулярных выражений для извлечения URL-адресов из простого текста с помощью Perl - PullRequest
5 голосов
/ 27 июня 2009

Как я могу использовать регулярные выражения Perl для извлечения всех URL-адресов определенного домена (возможно с переменными поддоменами) с определенным расширением из простого текста? Я пробовал:

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";
}

Это ужасно терпит неудачу и дает мне:

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

Я думал, что этого не произойдет, потому что я использую .*?, который должен быть не жадным и дать мне наименьшее совпадение. Может кто-нибудь сказать мне, что я делаю не так? (Я не хочу, чтобы какой-то сверхсложный, регулярный регулярный оператор проверял URL-адреса; я хочу знать, что я делаю неправильно, чтобы я мог извлечь из этого уроки.)

Ответы [ 7 ]

16 голосов
/ 27 июня 2009

URI :: Find специально разработан для решения этой проблемы. Он найдет все URI, а затем вы сможете отфильтровать их. У него есть несколько эвристик для обработки таких вещей, как конечная пунктуация.

ОБНОВЛЕНИЕ: недавно обновлено для обработки Unicode.

5 голосов
/ 27 июня 2009

Визит CPAN : Регулярное выражение :: Общий :: URI

Редактировать : Даже если вам не нужно постоянное регулярное выражение, оно может помочь вам взглянуть на источник протестированного модуля, который работает.

Если вы хотите найти URL-адреса, соответствующие определенной строке, вы можете легко использовать этот модуль для этого.

#!/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/;
  }
}
2 голосов
/ 02 мая 2012

Я использовал следующий код для извлечения ссылок, которые заканчиваются определенным расширением
, например * .htm, * .html, * .gif, * .jpeg. Примечание. В этом сценарии сначала пишется расширение * .html, а затем * .htm, поскольку оба имеют общий «htm». Так что изменения такого рода следует делать осторожно.

Ввод: Имя файла со ссылками и Имя выходного файла, в котором будут сохранены результаты.
Вывод: Будет сохранен в выходном файле.

Код идет здесь:

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 );

Вывод вашей строки здесь:

http://homepage.com/woot.gif
http://shomepage.com/woot.gif
1 голос
/ 11 мая 2016
https?\:\/\/[^\s]+[\/\w]

Это регулярное выражение работает для меня

1 голос
/ 30 июня 2009

URL не могут содержать пробелы, поэтому вместо. *? Вы должны использовать \ S * ?, для нуля или более непробельных символов.

0 голосов
/ 06 августа 2011

Вот регулярное выражение (надеюсь) получить | извлечь | получить все URL из строки | текстового файла, который, кажется, работает для меня:

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

... или в примере:

$ 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

Для справки по noob вот отладочная версия этой же команды:

$ 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"} }'

Регулярное выражение совпадает с http(s):// - и использует пробелы, " и ) в качестве символов «выхода»; затем использует положительный прогноз , чтобы первоначально вызвать «выход» в буквальной группе «http» (если совпадение уже выполняется); однако, поскольку это также «съедает» последний символ предыдущего совпадения, здесь совпадение с предварительным просмотром перемещается на один символ вперед на «ttp:».

Некоторые полезные страницы:

Надеюсь, это кому-нибудь поможет,
Ура!

РЕДАКТИРОВАТЬ: Ups, только что нашел около URI :: Find :: Simple - search.cpan.org , похоже, делает то же самое ( через regex - получение заголовка сайта по ссылке в строке )

0 голосов
/ 28 июня 2009

Я думал, что это не должно произойти, потому что я использую. *? который должен быть нежадным и дать мне наименьшее совпадение

Да, но дает наименьшее совпадение вправо . Начиная с первого http и заканчивая направо, это наименьшее совпадение.

Обратите внимание, что в будущем вам не нужно избегать косых черт, потому что вам не нужно использовать косые черты в качестве разделителя. И вам не нужно бежать из толстой кишки. В следующий раз просто сделайте это:

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

или

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

или

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

или один из множества других символов, см. Документацию perlre.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...