繁体   English   中英

pyparsing问题

[英]pyparsing question

此代码有效:

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-如何确定字符串解析为。 “ 80001”解析为“邮政编码”,但是如何使用pyparsing确定呢? 我不是在分析字符串的内容,而只是确定它是哪种查询。

您可以分别使用邮政编码和foo,以便您知道字符串与哪一个匹配。

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

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

您可以做的是从中继承子类,并根据需要重写方法以自定义行为,然后改用子类。

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

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和zipcode表达式来执行此操作:

# 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提供的解析类不仅仅是Regex(例如Word,Keyword,Literal,CaselessLiteral),而且您可以通过将解析器与“ +”,“ |”,“ ^”,“〜”,“ @”和“ '*'运算符。 例如,如果您想解析美国的社会保险号,但不使用正则表达式,则可以使用:

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

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

如果您想解析此类数字的可能列表,以“ /”分隔,请使用:

delimitedList(ssn, '/')

或者,如果此类数字介于1到3之间且没有斜线,请使用:

ssn * (1,3)

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

当我写pyparsing时,我的意图是由基本构建块组成的解析器的组合将是创建解析器的主要形式。 直到后来的版本中,我才添加了Regex作为最终的逃生阀门-如果人们无法建立他们的解析器,他们可能会退回到regex的格式,这肯定证明了它的强大功能。

或者,正如另一位发布者所建议的,您可以打开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']

(请注意省略尾随单号“?”)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM