Perl和模式匹配

时间:2013-03-17 07:45:55

标签: perl

我一直在做一些带有参考书目的html文件的东西,并除了作者之外将所有内容都删除。我很难摆脱一些无关的数据,比如html标签中的字符。我希望能够在标签之间删除整个标签甚至更好的特定数据。

现在这就是我的潜艇的样子:

    sub extractAuthorsIntoArray{
        @author_array = split /[<>"\/?!.=\(\)1234567890':]/, $doc;
        foreach(@author_array){
            print "$_" . "\n";
        }
    }

此时它所做的是删除所有标记字符,但它留下了一堆我不想要的无关数据,例如发布日期以及发布名称和我不需要的其他数据。任何时候我试图摆脱说“&lt; li&gt;”它给了我新的数据,完全没有这些字符。无论如何,我会继续抨击它。

Laters。

编辑:

我想做的是采取以下措施:

&LT; li value =“2”&gt; Artem Chebotko和Shiyong Lu,&lt; b&gt;“用于有效评估SPARQL嵌套可选图形模式的嵌套可选连接”&lt; / B取代。 &LT; i>用于语义Web演进的渐进概念:应用和开发&lt; / i&gt;,Miltiadis Lytras和Amit Sheth(Eds。),Information Science Publishing,ISBN 160566992X,2010。&lt; BR /&GT;&LT; BR /&GT;&LT; /立GT; &LT; li&gt; Artem Chebotko,Shiyong Lu,Farshad Fotouhi和Anthony Aristar,&lt; b>“用于语义Web的多媒体语言数据的基于本体的注释”&lt; / B取代。 &LT; i&gt;基于语义Web的信息系统:最先进的应用程序&lt; / i&gt;,Amit Sheth和Miltiadis Lytras(编辑),IGI Global,ISBN 1599044269,2006。&lt; BR /&GT;&LT; BR /&GT;&LT; /立GT;

最后得到这个:

Artem Chebotko和Shiyong Lu

4 个答案:

答案 0 :(得分:1)

我的建议:不要使用正则表达式。取而代之的是,使用HTML::Parser或CPAN提供的众多模块之一。

答案 1 :(得分:1)

一般来说,如果没有对数据结构的确定性,问题很难解决,但根据您的示例,我会假设作者始终是您数据的第一个非标记内容并被终止用逗号(这是一种非常常见的格式)。

这意味着问题有两个部分:剥离任何初始HTML标记,然后删除逗号后面的所有内容。

首先,HTML标记很容易识别,因为它以<开头,以>结尾,不能包含其中任何一个字符。所以:

$line =~ s{ \A \s* (?: < [^>]+ > \s* )+ }{}xms;

将删除行开头的所有HTML标记(和空格)。 (这使用{em> Perl最佳实践建议的/x标志和其他编码样式。)逐步完成此操作,\A匹配字符串的开头{{ 1}}匹配任意数量的空格,核心是\s*,它通过查找标记的开头然后取一个或多个字符直到标记的结尾来匹配HTML标记。这包含在< [^>]+ >中以允许任意数量的(?: )+。 (我正在使用(?:)而不仅仅是(),因为如果您不关心保持匹配,最好关闭捕获。)

之后从逗号中删除所有内容要容易得多:

$line =~ s{ , .* }{}xms;

现在,假设每个bibiography条目都是程序中的单个标量。这掩盖了一个相当大的问题;如果你有一个包含整个页面的变量,你可能需要解析它。如果每个条目都是<li>标记,您要执行的操作是提取每个<li>标记的内容,然后按上述方式对其进行处理。

为此,请在列表上下文中使用/g选项进行匹配,执行以下操作:

my @entries = ($doc =~ m{ <li (?: \s [^>] )? > (.*?) </li> }xmsg);

这里有一些细微之处。 (?: )?之后的<li位可选地匹配空格,后跟除>以外的一些字符,以允许该标记的任何属性。 (.*?)部分执行提取标记内容的实际工作。请注意?之后的*。这使得匹配非贪婪,这意味着它不是将所有内容与文档中的 last </li>标记进行匹配,而是匹配 first 之前的所有内容。 </li>标记。最后,/g修饰符表示要尽可能多地重复此匹配,并将捕获()的内容作为列表返回。

答案 2 :(得分:1)

这是一种相当......不寻常......使用split的方法。当您拥有包含由分隔符分隔的多个数据项的数据时,通常会使用它来拆分这些分隔符上的数据并检索单个项目。这不是你想在这里做的,所以split可能不是你正在寻找的 droid 命令。

正如已经提到的,正确的HTML解析器确实是这样做的正确方法,但你特别想要将regex用于教育目的,所以我会给你一个。请注意,使用正则表达式解析HTML充满了危险,并且几乎可以肯定会出现这种情况,但这种情况会失败。

所以,那说:

#!/usr/bin/env perl    

use strict;
use warnings;
use 5.010;

my $text = q[< li value="2">Artem Chebotko and Shiyong Lu, < b>"Nested Optional Join for Efficient Evaluation of SPARQL Nested Optional Graph Patterns"< /b>. < i>Progressive Concepts for Semantic Web Evolution: Applications and Developments< /i>, Miltiadis Lytras and Amit Sheth (Eds.), Information Science Publishing, ISBN 160566992X, 2010.< br/>< br/>< /li> < li>Artem Chebotko, Shiyong Lu, Farshad Fotouhi, and Anthony Aristar, < b>"Ontology-Based Annotation of Multimedia Language Data for the Semantic Web"< /b>. < i>Semantic Web-Based Information Systems: State-of-the-Art Applications< /i>, Amit Sheth and Miltiadis Lytras (Eds.), IGI Global, ISBN 1599044269, 2006.< br/>< br/>< /li>];

my @list_items = $text =~ m[<\s*li(?:\s+[^>]*)?>(.*?)<\s*/li\s*>]g;

my @authors;
for (@list_items) {
  /([^<]+), </;
  push @authors, $1;
}

say for @authors;

输出:

Artem Chebotko and Shiyong Lu
Artem Chebotko, Shiyong Lu, Farshad Fotouhi, and Anthony Aristar

答案 3 :(得分:0)

#!/usr/bin/perl -w

use strict;
read DATA, my $string, -s DATA;
my @matches = ( $string =~ /<\s+li\s*(?:.*?)>(.+?),\s+<\s+b>/g );
print "$_\n\n" foreach (@matches);

__DATA__
< li value="2">Artem Chebotko and Shiyong Lu, < b>"Nested Optional Join for Efficient Evaluation of SPARQL Nested Optional Graph Patterns"< /b>. < i>Progressive Concepts for Semantic Web Evolution: Applications and Developments< /i>, Miltiadis Lytras and Amit Sheth (Eds.), Information Science Publishing, ISBN 160566992X, 2010.< br/>< br/>< /li> < li>Artem Chebotko, Shiyong Lu, Farshad Fotouhi, and Anthony Aristar, < b>"Ontology-Based Annotation of Multimedia Language Data for the Semantic Web"< /b>. < i>Semantic Web-Based Information Systems: State-of-the-Art Applications< /i>, Amit Sheth and Miltiadis Lytras (Eds.), IGI Global, ISBN 1599044269, 2006.< br/>< br/>< /li>

如果您愿意解决这个具体问题,那么您的正则表达式应该是:

a) < li value="2">AUTHORS, < b>
b) < li>AUTHORS, < b>

对于a)一个可能的正则表达式是:

< \s+ li \s+ value="2"> (.+), \s+ <\s+b>

对于b)一个可能的正则表达式是:

< \s+ li> (.+), \s+ <\s+b>

结合这两个正则表达式:

<\s+li\s*(?:.*?)>(.+?),\s+<\s+b>

不优雅&amp;等等,但也许它会帮助你。