首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >pyparsing问题

pyparsing问题
EN

Stack Overflow用户
提问于 2010-02-06 18:59:07
回答 3查看 921关注 0票数 1

下面的代码可以工作:

代码语言:javascript
复制
from pyparsing import *

zipRE = "\d{5}(?:[-\s]\d{4})?" 
fooRE = "^\!\s+.*"

zipcode = Regex( zipRE )
foo = Regex( fooRE )

query = ( zipcode | foo )



tests = [ "80517", "C6H5OH", "90001-3234", "! sfs" ]

for t in tests:
    try:
        results = query.parseString( t )
        print t,"->", results
    except ParseException, pe:
        print pe

我被两个问题卡住了:

1-如何使用自定义函数解析token。例如,如果我想使用一些自定义逻辑而不是正则表达式来确定一个数字是否为邮政编码。而不是:

代码语言:javascript
复制
zipcode = Regex( zipRE )

也许:

代码语言:javascript
复制
zipcode = MyFunc()

2-如何确定字符串要解析的内容。"80001“解析为"zipcode”,但是如何使用pyparsing确定?我不是解析字符串的内容,而是简单地确定它是哪种类型的查询。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2010-02-07 00:41:11

你的第二个问题很简单,所以我先回答这个问题。更改查询以将结果名称分配给不同的表达式:

代码语言:javascript
复制
query = ( zipcode("zip") | foo("foo") ) 

现在您可以对返回的结果调用getName():

代码语言:javascript
复制
print t,"->", results, results.getName()

给予:

代码语言:javascript
复制
80517 -> ['80517'] zip
Expected Re:('\\d{5}(?:[-\\s]\\d{4})?') (at char 0), (line:1, col:1)
90001-3234 -> ['90001-3234'] zip
! sfs -> ['! sfs'] foo

如果您打算使用结果的fooness或zipness来调用另一个函数,则可以在解析时通过将解析操作附加到foo和zipcode表达式来完成此操作:

代码语言:javascript
复制
# enclose zipcodes in '*'s, foos in '#'s
zipcode.setParseAction(lambda t: '*' + t[0] + '*')
foo.setParseAction(lambda t: '#' + t[0] + '#')

query = ( zipcode("zip") | foo("foo") ) 

现在给出:

代码语言:javascript
复制
80517 -> ['*80517*'] zip
Expected Re:('\\d{5}(?:[-\\s]\\d{4})?') (at char 0), (line:1, col:1)
90001-3234 -> ['*90001-3234*'] zip
! sfs -> ['#! sfs#'] foo

对于你的第一个问题,我不是很清楚你指的是什么类型的函数。Pyparsing提供了比Regex多得多的解析类(如Word、Keyword、Literal、CaselessLiteral),您可以通过将它们与'+‘、'|’、'^‘、'~’、'@‘和'*’运算符组合在一起来组成解析器。例如,如果您希望解析美国社会安全号码,但不使用正则表达式,则可以使用:

代码语言:javascript
复制
ssn = Combine(Word(nums,exact=3) + '-' + 
        Word(nums,exact=2) + '-' + Word(nums,exact=4))

单词匹配对于在其构造函数中由给定字符组成的连续“单词”,Combine将匹配的标记连接到单个标记中。

如果您想要解析这类数字的潜在列表,请使用:

代码语言:javascript
复制
delimitedList(ssn, '/')

或者,如果有1到3个这样的数字,并且没有分隔符,请使用:

代码语言:javascript
复制
ssn * (1,3)

并且任何表达式都可以附加结果名称或解析操作,以进一步丰富解析结果或解析过程中的功能。您甚至可以使用Forward类构建递归解析器,例如括号的嵌套列表、算术表达式等。

当我编写pyparsing时,我的意图是希望这种由基本构建块组成的解析器将成为创建解析器的主要形式。直到后来的版本中,我才添加了Regex作为(我认为是)最终的逃生阀-如果人们不能构建他们的解析器,他们可以求助于regex的格式,这已经随着时间的推移证明了它的强大功能。

或者,正如另一个帖子所建议的那样,您可以打开pyparsing源代码,然后继承现有类中的一个类,或者根据它们的结构编写自己的类。下面是一个匹配成对字符的类:

代码语言:javascript
复制
class PairOf(Token):
    """Token for matching words composed of a pair
       of characters in a given set.
    """
    def __init__( self, chars ):
        super(PairOf,self).__init__()
        self.pair_chars = set(chars)

    def parseImpl( self, instring, loc, doActions=True ):
        if (loc < len(instring)-1 and 
           instring[loc] in self.pair_chars and
           instring[loc+1] == instring[loc]):
            return loc+2, instring[loc:loc+2]
        else:
            raise ParseException(instring, loc, "Not at a pair of characters")

因此:

代码语言:javascript
复制
punc = r"~!@#$%^&*_-+=|\?/"
parser = OneOrMore(Word(alphas) | PairOf(punc))
print parser.parseString("Does ** this match @@@@ %% the parser?")

提供:

代码语言:javascript
复制
['Does', '**', 'this', 'match', '@@', '@@', '%%', 'the', 'parser']

(注意尾部单曲‘?’的省略部分)

票数 2
EN

Stack Overflow用户

发布于 2010-02-06 19:20:06

您可以分别使用zipcode和foo,这样就可以知道字符串匹配的是哪一个。

代码语言:javascript
复制
zipresults = zipcode.parseString( t )
fooresults = foo.parseString( t )
票数 3
EN

Stack Overflow用户

发布于 2010-02-06 19:51:31

我没有pyparsing模块,但Regex必须是一个类,而不是函数。

你能做的就是继承它的子类,并根据需要覆盖方法,以自定义行为,然后使用你的子类。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/2212860

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档