在Perl或Python中模拟lex的功能

4 投票
8 回答
1545 浏览
提问于 2025-04-11 09:28

事情是这样的。有没有办法根据多个正则表达式把字符串分割成小块?

举个例子:

我需要获取所有的href标签、它们对应的文本,以及根据不同的正则表达式提取一些其他文本。

所以我有三个表达式,想把这一行分割开来,提取出每个表达式匹配的文本块。

其实我已经用flex做过这个(别搞混了,跟Adobe的那个不一样),flex是老牌的lex的一个实现。lex提供了一种优雅的方法,通过根据表达式执行“动作”来完成这个任务。你还可以控制lex读取文件的方式(按块或按行读取)。

问题是,flex实际上会生成C/C++代码来完成分割的工作。我有一个make文件把这些东西都包装起来了。

我在想,perl或python能不能以某种方式做到同样的事情。其实我希望能在一个编程语言里完成所有的工作。

分割只是我想在应用程序中做的事情之一。

除了perl或python,还有其他语言(包括函数式语言)能做到这一点吗?

我在这里读过关于PLY和ANTLR的内容(解析,在哪里可以学习)。

但是有没有办法在python中自然地做到这一点?请原谅我的无知,这些工具在任何流行的产品或服务中有用吗?

谢谢。

8 个回答

5

听起来你其实只是想解析HTML,我推荐你看看一些很棒的工具包来实现这个功能:

或者!你可以使用以下这些解析器:

  • PyParsing
  • DParser - 一个有很好的Python绑定的GLR解析器。
  • ANTLR - 一个递归下降的解析器生成器,可以生成Python代码。

这个例子来自于BeautifulSoup的文档

from BeautifulSoup import BeautifulSoup, SoupStrainer
import re

links = SoupStrainer('a')
[tag for tag in BeautifulSoup(doc, parseOnlyThese=links)]
# [<a href="http://www.bob.com/">success</a>, 
#  <a href="http://www.bob.com/plasma">experiments</a>, 
#  <a href="http://www.boogabooga.net/">BoogaBooga</a>]

linksToBob = SoupStrainer('a', href=re.compile('bob.com/'))
[tag for tag in BeautifulSoup(doc, parseOnlyThese=linksToBob)]
# [<a href="http://www.bob.com/">success</a>, 
#  <a href="http://www.bob.com/plasma">experiments</a>]
8

请查看以下模块的文档,地址在CPAN上。

HTML::TreeBuilder

HTML::TableExtract

还有

Parse::RecDescent

我用过这些模块来处理相当大且复杂的网页。

7

如果你想从网页中提取链接,那么Perl的WWW::Mechanize模块可以很优雅地帮你解决这个问题。下面是一个示例程序,它会抓取Stack Overflow的第一页,并提取出所有的链接,打印出它们的文本和对应的URL:

#!/usr/bin/perl
use strict;
use warnings;
use WWW::Mechanize;

my $mech = WWW::Mechanize->new;

$mech->get("http://stackoverflow.com/");

$mech->success or die "Oh no! Couldn't fetch stackoverflow.com";

foreach my $link ($mech->links) {
    print "* [",$link->text, "] points to ", $link->url, "\n";
}

在主循环中,每个 $link 都是一个WWW::Mechanize::Link对象,所以你不仅仅可以获取文本和URL。

祝一切顺利,

保罗

撰写回答