此代码的工作:

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 - 如何使用自定义函数来解析的令牌。举例来说,如果我想用一些自定义的逻辑,而不是一个正则表达式,以确定是否一个数是邮编。 代替:

zipcode = Regex( zipRE )

也许:

zipcode = MyFunc()

2 - 如何确定哪些解析字符串TO。 “80001”解析为“邮政编码”但我要如何确定这个使用pyparsing?我不解析其内容的字符串,而只是以确定它是什么样的查询。

有帮助吗?

解决方案

您的第二个问题是容易的,所以我会回答,第一。改变查询分配结果的名称不同的表达式:

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

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

print t,"->", results, results.getName()

,并提供:

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和邮政编码表达式做到这一点:

# enclose zipcodes in '*'s, foos in '#'s
zipcode.setParseAction(lambda t: '*' + t[0] + '*')
foo.setParseAction(lambda t: '#' + t[0] + '#')

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

现在给出:

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提供更多的解析类的不仅仅是正则表达式(如Word,关键字,文字,CaselessLiteral),你通过与“+”,结合撰写解析器“|”,“^”,“〜”,“@”和'*' 运算符。举例来说,如果你想解析了美国的社会安全号码,但不能使用正则表达式,你可以使用:

ssn = Combine(Word(nums,exact=3) + '-' + 
        Word(nums,exact=2) + '-' + Word(nums,exact=4))

Word为由在其构造给定字符的连续“字”相匹配,联合地连接了匹配令牌到单个令牌。

如果你想解析此类数量的潜在名单,由“/的分隔,使用:

delimitedList(ssn, '/')

或者如果有1个3这样的数字之间,没有delimters,使用:

ssn * (1,3)

和任何表达式可以具有结果的名称或解析附连到他们的动作,在分析过程中进一步丰富了解析的结果,或功能。甚至可以建立递归解析器,如使用正向类括号的嵌套的列表,算术表达式等。

我时写pyparsing意图是从基本构建块解析器该组合物将是创建解析器的主要形式。它只是在我添加正则表达式为(我虽然是)最终逃脱阀以后的版本 - 如果人们不能建立自己的解析器,他们可以依傍的正则表达式的格式,这无疑证明了它的力量随着时间的推移。

或者,就像一个其他的海报建议,您可以打开pyparsing源,和子类的现有类的一个,或写自己的,以下的结构。下面是将匹配用于配对字符的类:

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")

这样:

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

给出:

['Does', '**', 'this', 'match', '@@', '@@', '%%', 'the', 'parser']

(注意的省略的后单 '?')

其他提示

您可以单独使用邮政编码和Foo,让你知道字符串匹配其中之一。

zipresults = zipcode.parseString( t )
fooresults = foo.parseString( t )

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

你能做的是从它和重写方法的子类根据需要定制行为,然后用你的子类来代替。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top