使用 pyparsing 解析行数据直到关键字
Parse line data until keyword with pyparsing
我正在尝试解析行数据,然后将它们分组到列表中。
这是我的脚本:
from pyparsing import *
data = """START
line 2
line 3
line 4
END
START
line a
line b
line c
END
"""
EOL = LineEnd().suppress()
start = Keyword('START').suppress() + EOL
end = Keyword('END').suppress() + EOL
line = SkipTo(LineEnd()) + EOL
lines = start + OneOrMore(start | end | Group(line))
start.setDebug()
end.setDebug()
line.setDebug()
result = lines.parseString(data)
results_list = result.asList()
print(results_list)
此代码的灵感来自另一个 Whosebug 问题:
Matching nonempty lines with pyparsing
我需要的是逐行解析从START到END的所有内容,并将其保存到每组列表中(从START到匹配END的所有内容都是一组)。然而这个脚本把每一行都放在新组中。
这是结果:
[['line 2'], ['line 3'], ['line 4'], ['line a'], ['line b'], ['line c'], ['']]
我希望它是:
[['line 2', 'line 3', 'line 4'], ['line a', 'line b', 'line c']]
它还在最后解析了一个空字符串。
我是一个 pyparsing 初学者,所以我请求你的帮助。
谢谢
您可以使用 nestedExpr
查找由 START
和 END
分隔的文本。
如果你使用
In [322]: pp.nestedExpr('START', 'END').searchString(data).asList()
Out[322]:
[[['line', '2', 'line', '3', 'line', '4']],
[['line', 'a', 'line', 'b', 'line', 'c']]]
然后文本按空格拆分。 (请注意,在我们想要 'line 2'
的位置上方有 'line', '2'
)。我们宁愿它只在 '\n'
上拆分。所以要解决这个问题,我们可以使用 pp.nestedExpr
函数的 content
参数,它允许我们控制什么被认为是嵌套列表中的项目。
nestedExpr
的源代码定义了
content = (Combine(OneOrMore(~ignoreExpr +
~Literal(opener) + ~Literal(closer) +
CharsNotIn(ParserElement.DEFAULT_WHITE_CHARS,exact=1))
).setParseAction(lambda t:t[0].strip()))
默认情况下,其中 pp.ParserElement.DEFAULT_WHITE_CHARS
是
In [324]: pp.ParserElement.DEFAULT_WHITE_CHARS
Out[324]: ' \n\t\r'
这就是导致 nextExpr
在所有空白处拆分的原因。
因此,如果我们将其简化为 '\n'
,那么 nestedExpr
会将内容拆分为
行而不是所有空格。
import pyparsing as pp
data = """START
line 2
line 3
line 4
END
START
line a
line b
line c
END
"""
opener = 'START'
closer = 'END'
content = pp.Combine(pp.OneOrMore(~pp.Literal(opener)
+ ~pp.Literal(closer)
+ pp.CharsNotIn('\n',exact=1)))
expr = pp.nestedExpr(opener, closer, content=content)
result = [item[0] for item in expr.searchString(data).asList()]
print(result)
产量
[['line 2', 'line 3', 'line 4'], ['line a', 'line b', 'line c']]
我正在尝试解析行数据,然后将它们分组到列表中。
这是我的脚本:
from pyparsing import *
data = """START
line 2
line 3
line 4
END
START
line a
line b
line c
END
"""
EOL = LineEnd().suppress()
start = Keyword('START').suppress() + EOL
end = Keyword('END').suppress() + EOL
line = SkipTo(LineEnd()) + EOL
lines = start + OneOrMore(start | end | Group(line))
start.setDebug()
end.setDebug()
line.setDebug()
result = lines.parseString(data)
results_list = result.asList()
print(results_list)
此代码的灵感来自另一个 Whosebug 问题: Matching nonempty lines with pyparsing
我需要的是逐行解析从START到END的所有内容,并将其保存到每组列表中(从START到匹配END的所有内容都是一组)。然而这个脚本把每一行都放在新组中。
这是结果:
[['line 2'], ['line 3'], ['line 4'], ['line a'], ['line b'], ['line c'], ['']]
我希望它是:
[['line 2', 'line 3', 'line 4'], ['line a', 'line b', 'line c']]
它还在最后解析了一个空字符串。
我是一个 pyparsing 初学者,所以我请求你的帮助。
谢谢
您可以使用 nestedExpr
查找由 START
和 END
分隔的文本。
如果你使用
In [322]: pp.nestedExpr('START', 'END').searchString(data).asList()
Out[322]:
[[['line', '2', 'line', '3', 'line', '4']],
[['line', 'a', 'line', 'b', 'line', 'c']]]
然后文本按空格拆分。 (请注意,在我们想要 'line 2'
的位置上方有 'line', '2'
)。我们宁愿它只在 '\n'
上拆分。所以要解决这个问题,我们可以使用 pp.nestedExpr
函数的 content
参数,它允许我们控制什么被认为是嵌套列表中的项目。
nestedExpr
的源代码定义了
content = (Combine(OneOrMore(~ignoreExpr +
~Literal(opener) + ~Literal(closer) +
CharsNotIn(ParserElement.DEFAULT_WHITE_CHARS,exact=1))
).setParseAction(lambda t:t[0].strip()))
默认情况下,其中 pp.ParserElement.DEFAULT_WHITE_CHARS
是
In [324]: pp.ParserElement.DEFAULT_WHITE_CHARS
Out[324]: ' \n\t\r'
这就是导致 nextExpr
在所有空白处拆分的原因。
因此,如果我们将其简化为 '\n'
,那么 nestedExpr
会将内容拆分为
行而不是所有空格。
import pyparsing as pp
data = """START
line 2
line 3
line 4
END
START
line a
line b
line c
END
"""
opener = 'START'
closer = 'END'
content = pp.Combine(pp.OneOrMore(~pp.Literal(opener)
+ ~pp.Literal(closer)
+ pp.CharsNotIn('\n',exact=1)))
expr = pp.nestedExpr(opener, closer, content=content)
result = [item[0] for item in expr.searchString(data).asList()]
print(result)
产量
[['line 2', 'line 3', 'line 4'], ['line a', 'line b', 'line c']]