使用正则表达式从Perl中提取纯文本的URL

时间:2009-06-27 18:07:52

标签: regex perl url

如何使用Perl regexp从纯文本中提取具有特定扩展名的特定域(可能具有可变子域)的所有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

我认为这不会发生,因为我正在使用.*?,这应该是非贪婪的,并给我最小的匹配。谁能告诉我我做错了什么? (我不想要一些超级复杂的,预制的regexp来验证URL;我想知道我做错了什么,所以我可以从中学习。)

7 个答案:

答案 0 :(得分:16)

URI::Find专门用于解决此问题。它将找到所有URI,然后您可以过滤它们。它有一些启发式处理跟踪标点符号等内容。

更新:最近更新以处理Unicode。

答案 1 :(得分:5)

访问CPANRegexp::Common::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 :(得分:2)

我使用以下代码来提取以特定扩展名结尾的链接,例如* .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

答案 3 :(得分:1)

不允许网址包含空格,而不是。*?你应该使用\ S * ?,为零或多个非空格字符。

答案 4 :(得分:1)

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

这个正则表达式对我有用

答案 5 :(得分:0)

  

我认为这不应该发生,因为我正在使用。*?应该是非贪婪的,给我最小的比赛

确实如此,但它为您提供了最小的匹配正确。从第一个http开始向右,这是最小的匹配。

请注意将来,您不必转义斜杠,因为您不必使用斜杠作为分隔符。而且你也不必逃过冒号。下次就这样做:

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

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

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

或许多其他字符之一,请参阅perlre文档。

答案 6 :(得分:0)

这是一个正则表达式(希望)从字符串文本文件中获取所有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)://匹配 - 并使用空格,")作为“退出”字符;然后使用positive lookahead,最初导致“http”文字组“退出”(如果匹配已在进行中);但是,由于这也“吃掉”上一场比赛的最后一个字符,这里的前瞻匹配将一个字符向前移动到“ttp:”。

一些有用的网页:

希望这有助于某人,
干杯!

编辑:Ups,刚刚找到关于URI::Find::Simple - search.cpan.org,似乎做同样的事情(通过regex - Getting the website title from a link in a string