使用停止标记解析字符串
Parsing strings with stop tokens
假设一个解析器接受字母 a
、b
和 c
以及这三者的任意组合。我想用满足以下条件的子字符串调用一个函数:
- 子字符串以
a
开头
- 子串在遇到
abc
之前终止
- 子字符串不以
abc
开头
例如我们有以下字符串:
bb cc ab bc cb bc abc bca bbb acc cbc ccc abc
我想用字符串 ab bc cb
和 acc cbc ccc
调用函数
我尝试按如下方式实现:
import pyparsing as pp
x = pp.OneOrMore(pp.Word("abc") + ~pp.Literal("abc"))
x.addCondition(lambda tokens: tokens[0] != "abc")
x.addCondition(lambda tokens: tokens[0][0] == "a")
x.addParseAction(lambda tokens: print("x)", tokens)) # Print action for debugging
y = pp.Word("abc")
y.addParseAction(lambda tokens: print("y)", tokens))
text = pp.OneOrMore(x ^ y)
text.parseString("bb cc ab bc cb bc abc bca bbb acc cbc ccc abc")
但是由于某些原因,这个 停止 1 个字太快了,这是输出:
y) ['bb']
y) ['cc']
x) ['ab', 'bc', 'bc']
y) ['cb']
y) ['abc']
y) ['bca']
y) ['bbb']
x) ['acc', 'cbc']
y) ['ccc']
y) ['abc']
此外,如果 abc
停止标记是一个不同字符串的列表,所有字符串都将用作停止标记,我该如何解析它?
所以像这样:
stopStrings = ["abc", "bca"]
x = pp.OneOrMore(pp.Word("abc") + ~pp.OneOf(stopStrings))
...
希望这能说明问题,感谢您的帮助!
这可能接近您想要的。我不明白你的第三个条件。
-
token
的定义坚持认为它 不是 之一 stop_tokens
并且它是 Word
由任意集合 {a,b,c} 中的字母。
- 当
token
被识别时 setParseAction
发送一个请求,如果它的第一个字符是 'a'. 则显示它
- 整个
parser
只是任意数量的 token
后跟任意数量的 stop_token
。每个 stop_token
在此上下文中被抑制。同时,如果识别出 stop_token
,则会发出一条消息,指示已看到一个。
代码:
import pyparsing as pp
def report_a(s):
try:
if s[0][0]=='a':
print (s[0], "begins with 'a'")
except:
pass
def report(s):
print ('stop token encountered')
stop_tokens = pp.Or([pp.Literal('abc'), pp.Literal('bca')])
token = pp.NotAny(stop_tokens) + pp.Word('abc').setParseAction(lambda s: report_a(s))
parser = pp.ZeroOrMore(token) + pp.ZeroOrMore(stop_tokens).setParseAction(lambda s: report(s)).suppress()
text = 'bb cc ab bc cb bc abc bca bbb acc cbc ccc abc'
print (parser.parseString(text))
结果:
ab begins with 'a'
stop token encountered
['bb', 'cc', 'ab', 'bc', 'cb', 'bc']
我想我明白了。 Bill Bell 的回答帮助我获得了 1 个以上的终止字符串。
stop_strings = ["abc", "acb"]
stop_tokens = pp.Or([pp.Literal(sub) for sub in stop_strings])
x = pp.OneOrMore(~stop_tokens + pp.Word("abc")) + pp.Optional(stop_tokens.suppress())
x.addCondition(lambda tokens: tokens[0][0] == "a")
x.addParseAction(lambda tokens: print("x)", tokens)) # Print action for debugging
y = pp.Word("abc")
y.addParseAction(lambda tokens: print("y)", tokens))
text = pp.OneOrMore(x ^ y)
text.parseString("bb cc acb ab cb abc bca bbb acc cbc ccc")
输出:
y) ['bb']
y) ['cc']
y) ['acb']
x) ['ab', 'cb']
y) ['bca']
y) ['bbb']
x) ['acc', 'cbc', 'ccc']
假设一个解析器接受字母 a
、b
和 c
以及这三者的任意组合。我想用满足以下条件的子字符串调用一个函数:
- 子字符串以
a
开头
- 子串在遇到
abc
之前终止
- 子字符串不以
abc
开头
例如我们有以下字符串:
bb cc ab bc cb bc abc bca bbb acc cbc ccc abc
我想用字符串 ab bc cb
和 acc cbc ccc
我尝试按如下方式实现:
import pyparsing as pp
x = pp.OneOrMore(pp.Word("abc") + ~pp.Literal("abc"))
x.addCondition(lambda tokens: tokens[0] != "abc")
x.addCondition(lambda tokens: tokens[0][0] == "a")
x.addParseAction(lambda tokens: print("x)", tokens)) # Print action for debugging
y = pp.Word("abc")
y.addParseAction(lambda tokens: print("y)", tokens))
text = pp.OneOrMore(x ^ y)
text.parseString("bb cc ab bc cb bc abc bca bbb acc cbc ccc abc")
但是由于某些原因,这个 停止 1 个字太快了,这是输出:
y) ['bb']
y) ['cc']
x) ['ab', 'bc', 'bc']
y) ['cb']
y) ['abc']
y) ['bca']
y) ['bbb']
x) ['acc', 'cbc']
y) ['ccc']
y) ['abc']
此外,如果 abc
停止标记是一个不同字符串的列表,所有字符串都将用作停止标记,我该如何解析它?
所以像这样:
stopStrings = ["abc", "bca"]
x = pp.OneOrMore(pp.Word("abc") + ~pp.OneOf(stopStrings))
...
希望这能说明问题,感谢您的帮助!
这可能接近您想要的。我不明白你的第三个条件。
-
token
的定义坚持认为它 不是 之一stop_tokens
并且它是Word
由任意集合 {a,b,c} 中的字母。 - 当
token
被识别时setParseAction
发送一个请求,如果它的第一个字符是 'a'. 则显示它
- 整个
parser
只是任意数量的token
后跟任意数量的stop_token
。每个stop_token
在此上下文中被抑制。同时,如果识别出stop_token
,则会发出一条消息,指示已看到一个。
代码:
import pyparsing as pp
def report_a(s):
try:
if s[0][0]=='a':
print (s[0], "begins with 'a'")
except:
pass
def report(s):
print ('stop token encountered')
stop_tokens = pp.Or([pp.Literal('abc'), pp.Literal('bca')])
token = pp.NotAny(stop_tokens) + pp.Word('abc').setParseAction(lambda s: report_a(s))
parser = pp.ZeroOrMore(token) + pp.ZeroOrMore(stop_tokens).setParseAction(lambda s: report(s)).suppress()
text = 'bb cc ab bc cb bc abc bca bbb acc cbc ccc abc'
print (parser.parseString(text))
结果:
ab begins with 'a'
stop token encountered
['bb', 'cc', 'ab', 'bc', 'cb', 'bc']
我想我明白了。
stop_strings = ["abc", "acb"]
stop_tokens = pp.Or([pp.Literal(sub) for sub in stop_strings])
x = pp.OneOrMore(~stop_tokens + pp.Word("abc")) + pp.Optional(stop_tokens.suppress())
x.addCondition(lambda tokens: tokens[0][0] == "a")
x.addParseAction(lambda tokens: print("x)", tokens)) # Print action for debugging
y = pp.Word("abc")
y.addParseAction(lambda tokens: print("y)", tokens))
text = pp.OneOrMore(x ^ y)
text.parseString("bb cc acb ab cb abc bca bbb acc cbc ccc")
输出:
y) ['bb']
y) ['cc']
y) ['acb']
x) ['ab', 'cb']
y) ['bca']
y) ['bbb']
x) ['acc', 'cbc', 'ccc']