Skip to main content
 首页 » 编程设计

python之如何使用 pyparsing 获取匹配标记的位置

2025年05月04日8shihaiming

到目前为止,我已尝试使用“setParseAction”来获取匹配标记的位置,但它有时无法像我预期的那样工作。以此代码为例:

>>> from pyparsing import * 
>>>  
>>> Z = Literal('0') 
>>> POINT = Literal('.') 
>>> BIN_DIGITS = Word('01') 
>>> OCT_DIGITS = Word('01234567') 
>>> DEC_DIGITS = Word('0123456789') 
>>> HEX_DIGITS = Word('0123456789abcdefABCDEF') 
>>> DEC_INT = DEC_DIGITS.setParseAction(lambda t: int(t[0])) 
>>> BIN_INT = Combine(Z + ((Literal('b') | 'B')) + BIN_DIGITS).\ 
...         setParseAction(lambda t: int(t[0], 2)) 
>>> OCT_INT = Combine(Z + ((Literal('o') | 'O')) + OCT_DIGITS).\ 
...         setParseAction(lambda t: int(t[0], 8)) 
>>> HEX_INT = Combine(Z + ((Literal('x') | 'X')) + HEX_DIGITS).\ 
...         setParseAction(lambda t: int(t[0], 16)) 
>>> INTEGER = HEX_INT | OCT_INT | BIN_INT | DEC_INT 
>>> EXP = Combine(CaselessLiteral('E') + Optional(Literal('+') | '-') + DEC_INT) 
>>> POINT_FLOAT = Combine(Optional(DEC_INT) + POINT + DEC_INT) | \ 
...         Combine(DEC_INT + POINT) 
>>> EXP_FLOAT = Combine(DEC_INT + EXP) | Combine(POINT_FLOAT + EXP) 
>>> FLOAT = (EXP_FLOAT | POINT_FLOAT).setParseAction(lambda t: float(t[0])) 
>>>  
>>>  
>>> def p(s, l, t): 
...     print 'Location of %s:  %s' % (t[0], l,) 
...  
>>>  
>>> NUMBER = (FLOAT | INTEGER).setParseAction(p) 
>>> NUMBER.parseString('    12345') 
Location of 12345:  0 
([12345], {}) 
>>> NUMBER.parseString(' 12345') 
Location of 12345:  0 
([12345], {}) 
>>> NUMBER.parseString('12345') 
Location of 12345:  0 
([12345], {}) 

无论我将数字“12345”放在字符串中的什么位置,位置始终为 0。但是,如果我尝试:

>>> LITERAL = Literal('someword').setParseAction(p) 
>>> LITERAL.parseString('    someword') 
Location of someword:  4 
(['someword'], {}) 
>>> LITERAL.parseString(' someword') 
Location of someword:  1 
(['someword'], {}) 
>>> LITERAL.parseString('someword') 
Location of someword:  0 
(['someword'], {}) 

它按预期工作。我在第一个示例中做错了什么?

请您参考如下方法:

好的,多亏了 Paul 的提示,我通过将“Or”表达式与压缩的空白表达式相结合,并使用它来解析字符串,设法解决了这个问题。这是最终结果:

>>> from pyparsing import * 
>>>  
>>> def p(s,l,t): 
...     print 'Location of %s: %s' % (s, l,) 
...  
>>> Z = Literal('0') 
>>> POINT = Literal('.') 
>>> BIN_DIGITS = Word('01') 
>>> OCT_DIGITS = Word('01234567') 
>>> DEC_DIGITS = Word('0123456789') 
>>> HEX_DIGITS = Word('0123456789abcdefABCDEF') 
>>> DEC_INT = DEC_DIGITS.copy().setParseAction(lambda t: int(t[0])) 
>>> BIN_INT = Combine(Z + ((Literal('b') | 'B')) + BIN_DIGITS).\ 
...         setParseAction(lambda t: int(t[0], 2)) 
>>> OCT_INT = Combine(Z + ((Literal('o') | 'O')) + OCT_DIGITS).\ 
...         setParseAction(lambda t: int(t[0], 8)) 
>>> HEX_INT = Combine(Z + ((Literal('x') | 'X')) + HEX_DIGITS).\ 
...         setParseAction(lambda t: int(t[0], 16)) 
>>> INTEGER = HEX_INT | OCT_INT | BIN_INT | DEC_INT 
>>> EXP = Combine(CaselessLiteral('E') + Optional(Literal('+') | Literal('-')) + DEC_DIGITS) 
>>> POINT_FLOAT = Combine(Optional(DEC_DIGITS) + POINT + DEC_DIGITS) | \ 
...         Combine(DEC_DIGITS + POINT) 
>>> EXP_FLOAT = Combine(DEC_DIGITS + EXP) | Combine(POINT_FLOAT + EXP) 
>>> FLOAT = (EXP_FLOAT | POINT_FLOAT).setParseAction(lambda t: float(t[0])) 
>>> NUMBER = (FLOAT | INTEGER).setParseAction(p) 
>>> NUMBER2 = Combine(ZeroOrMore(White(exact=1)).suppress() + NUMBER) 
>>>  
>>> NUMBER2.parseString('    12345') 
Location of     12345: 4 
(['12345'], {})