0

所以我有这个文件clip.txt,它只包含:

<a href="https://en.wikipedia.org/wiki/Kanye_West">Kanye West</a>, 
<a href="http://en.wikipedia.org/wiki/Chris_Martin">Chris Martin</a>

现在我想删除 <...> 之间的所有内容,以便我最终得到

坎耶·韦斯特,克里斯汀·马丁。

使用 perl 我有当前代码:

#!/usr/local/bin/perl

$file = 'clip.txt';
open(FILE, $file);
@lines = <FILE>;
close(FILE);
$line =  @lines[0];

while (index($line, "<") != -1) {
my $from = rindex($line, "<");
my $to = rindex($line, ">");

print $from;
print ' - ';
print $to;
print ' ';

print substr($line, $from, $to+1);
print '|'; // to see where the line stops
print "\n";
substr($line, $from, $to+1) = ""; //removes between lines
$counter += 1;

}

print $line;

所有“打印”行都是多余的,但对调试很有用。

现在结果变成:

138 - 141 </a>
|
67 - 125 <a href="http://http://en.wikipedia.org/wiki/Chris_Martin">Chris Martin|
61 - 64 </a>, |
0 - 50 <a href="https://en.wikipedia.org/wiki/Kanye_West">|
Kanye West

首先脚本找到 138 -141 之间的位置,并将其删除。然后它找到 67 - 125 但它删除了 67 - 137。接下来它找到 61 - 64 但它删除了 61 - 66。

为什么这样做?在底线上,它找到了 0 - 64,它完美地删除了。所以我在这里找不到逻辑。

4

4 回答 4

4

您可以使用s///运算符:

$line =~ s/<[^>]+>//g
于 2013-07-28T09:44:02.310 回答
4

substr的第三个参数是长度,不是结束索引,所以你应该通过$to-$from+1.

(尽管您还应该调整代码以确保它同时找到 a<和 a >,并且 the>位于 之后<。)

于 2013-07-28T10:28:04.527 回答
3

正确的解决方案确实是使用HTML::TokeParser::Simple 之类的东西。但是,如果您只是将其作为一个学习练习,您可以通过提取您想要的而不是删除您不想要的来简化它:

#!/usr/bin/env perl

use strict;
use warnings;
use feature 'say';

while (my $line = <DATA>) {
    my $x = index $line, '>';
    next unless ++$x;
    my $y = index $line, '<', $x;
    next unless $y >= 0;
    say substr($line, $x, $y - $x);
}

__DATA__
<a href="https://en.wikipedia.org/wiki/Kanye_West">Kanye West</a>,
<a href="http://en.wikipedia.org/wiki/Chris_Martin">Chris Martin</a>

输出:

肯伊·韦斯特
克里斯·马丁

另一方面,使用 HTML 解析器并没有那么复杂:

#!/usr/bin/env perl

use strict;
use warnings;
use feature 'say';

use HTML::TokeParser::Simple;

my $parser = HTML::TokeParser::Simple->new(\*DATA);

while (my $anchor = $parser->get_tag('a')) {
    my $text = $parser->get_text('/a');
    say $text;
}

__DATA__
<a href="https://en.wikipedia.org/wiki/Kanye_West">Kanye West</a>,
<a href="http://en.wikipedia.org/wiki/Chris_Martin">Chris Martin</a>
于 2013-07-28T10:07:50.480 回答
3

虽然简单的正则表达式替换应该对示例数据执行您想要的操作,但使用正则表达式解析 (X)HTML 通常是一个坏主意(并且使用简单的字符搜索做同样的事情基本上是相同的)。一种更灵活且可读性更好的方法是使用适当的 HTML 解析器。

Mojo::DOM示例:

#!/usr/bin/env perl

use strict;
use warnings;
use feature 'say';
use Mojo::DOM;

# slurp data into a parser object
my $dom = Mojo::DOM->new(do { local $/; <DATA> });

# iterate all links
for my $link ($dom->find('a')->each) {

    # print the link text
    say $link->text;
}

__DATA__
<a href="https://en.wikipedia.org/wiki/Kanye_West">Kanye West</a>, 
<a href="http://en.wikipedia.org/wiki/Chris_Martin">Chris Martin</a>

输出:

Kanye West
Chris Martin
于 2013-07-28T10:14:57.180 回答