sed/perl中的非贪婪正则表达式匹配

3
我正在尝试提取链接,使用命令为:sed /http.*.torrent/s/.*(http.*.torrent).*/\1/;/http.*.torrent/p 1.html。然而,由于sed缺乏非贪婪量词(这是因为在行尾的地方再次出现了“torrent”),我尝试将其转换为perl。但我需要perl的帮助。(或者如果您知道如何使用sed完成它,请告诉我。)现在我需要添加这部分内容,将其从sed转换过来:/http.*.torrent/p
这是命令:sed /http.*.torrent/s/.*(http.*.torrent).*/\1/;/http.*.torrent/p 1.html中的一部分。
但这也没有起作用;sed开始了但没有退出,并且按键时它们被回显但没有其他反应。

如果您提供了一个输入示例,解释了转换规则并展示了期望的输出,那么有人可以帮助您在Perl中完成它,而无需弄清sed代码试图做什么并失败。 - d5e5
This is an example of a matching line, other can be anything: <a href="https://toPB.torrent" title="Download this torrent"> The goal is to extract https://toPB.torrent for each such line. - ccvn
你是否正在尝试解析完整的HTML页面以提取.torrent链接?如果是这种情况,你可能需要深入研究HTML::TreeBuilder - ssapkota
2个回答

4

我建议使用经过充分验证的模块,如HTML::LinkExtor,来为您完成繁重的工作,并使用正则表达式简单地验证它发现的链接。请参见下面的示例,了解它可以有多么容易。

use Modern::Perl;
use HTML::LinkExtor;
use Data::Dumper;

my @links;


# A callback for LinkExtor. Disqualifies non-conforming links, and pushes
# into @links any conforming links.

sub callback {
    my ( $tag, %attr ) = @_;
    return if $tag ne 'a';
    return unless $attr{href} =~ m{http(?:s)?://[^/]*torrent}i;
    push @links, \%attr;
}


# The work is done here: Read the html file, parse it, and move on.
undef $/;
my $html = <DATA>;
my $p = HTML::LinkExtor->new(\&callback);
$p->parse( $html );

print Dumper \@links;

__DATA__
<a href="https://toPB.torrent" title="Download this torrent">The goal</a>
<a href="http://this.is.my.torrent.com" title="testlink">Testing2</a> <a href="http://another.torrent.org" title="bwahaha">Two links on one line</a>
<a href="https://toPBJ.torrent.biz" title="Last test">Final Test</a>
A line of nothingness...
That's all folks.

HTML::LinkExtor允许您设置回调函数。该模块本身解析HTML文档以查找任何链接。您要查找的是'a'链接(而不是'img'等)。因此,在回调函数中,除非您有一个'a'链接,否则请尽快退出。然后测试该“a”链接,以查看其中是否有“torrent”名称,并且在适当的位置。如果这个特定的正则表达式不是您需要的内容,那么您将需要更具体的内容,但我认为这就是您想要的。当找到链接时,它们被推送到数据结构中。在我的测试脚本结束时,我打印结构,以便您可以看到自己拥有什么。 __DATA__部分包含一些示例HTML片段,以及垃圾文本以验证它只能找到链接。
使用经过充分测试的模块来解析您的HTML比构建脆弱的正则表达式来完成整个工作要耐用得多。许多良好制作的解析解决方案在幕后包括正则表达式,但仅用于偶尔完成一些小工作。当您开始依赖regexp进行解析(而不是识别小构建块),您很快就会用尽汽油。
祝您玩得开心。

感谢您提供的信息丰富的答案。对于这种特殊情况,我不需要使用它,因为模式非常简单,但是我会记住HTML :: LinkExtor。 - ccvn

3

sed 不支持非贪婪匹配,所以最好的选择就是使用 perl

perl -ne '/.*?(http.*?.torrent)/ && print "$1\n"' 1.html
-n参数告诉perl读取输入的每一行(在这种情况下是从1.html中读取,如果没有文件,则从stdin中读取),并对每一行运行某些操作...-e在命令行上提供了"要执行的内容"。
表达式的第一部分与您要查找的表达式匹配,括号将有趣的部分捕获到$1中。如果它匹配,它将计算为真,然后执行打印(给您一个匹配项以及一个换行符)。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接