我有一个通用的“文本块”元素,我从文档中复制了空白剥离代码:
import pyparsing as pp
text_block = pp.Group(
pp.OneOrMore(
pp.SkipTo(pp.LineEnd()) + pp.LineEnd().suppress(),
stopOn=pp.StringEnd() | (pp.LineStart() + (pp.Literal("E)") | pp.Literal("F)")))
)
).set_parse_action(pp.token_map(str.strip))
不幸的是,这会返回一个错误:
失败异常:类型错误:“str”对象的描述符“strip” 不适用于“ParseResults”对象
我用函数替换了
token_map
的使用:
def _strip_whitespace(tokens):
return [token.str.strip() for token in tokens]
text_block = pp.Group(
pp.OneOrMore(
pp.SkipTo(pp.LineEnd()) + pp.LineEnd().suppress(),
stopOn=pp.StringEnd() | (pp.LineStart() + (pp.Literal("E)") | pp.Literal("F)")))
)
).set_parse_action(_strip_whitespace)
...但现在它删除了所有文本(!)
Pyparsing 默认情况下会自动处理 ParseResults 中的空格剥离。
pyparsing 模块处理一些在编写文本解析器时通常令人烦恼的问题:因此,除非您配置/指示它专门捕获空格,否则无需删除空格,因为它通常会自动删除。
额外或缺失的空格(上面的程序还将处理“Hello,World!”、“Hello , World !”等)
- 带引号的字符串
- 嵌入评论
SkipTo()
是可以捕获空白的
ParserElements
之一,因为它捕获当前解析位置和跳到字符之间的所有内容。这就是为什么,在
SkipTo
的 表解析示例中,他们在
token.strip()
的解析操作中使用 SkipTo
。但是只有解析器的SkipTo
元素需要剥离,并且您试图剥离所有标记,这是一个非常糟糕的主意,因为除了明确定义的情况外,不会有任何空格。因此,如果您要在解析操作中应用
str.strip
,则应该将 just放在
SkipTo
上。他们给出的 AtLineStart
示例对于此类匹配更为典型,通过
pp.rest_of_line
匹配每一行(这也会抓取空格):test = '''\
AAA this line
AAA and this line
AAA but not this one
B AAA and definitely not this one
'''
for t in (AtLineStart('AAA') + rest_of_line).search_string(test):
print(t)
对于您的文本块,您可以
只需跳到结束标记来抓取块中的所有行,然后在处理结果时处理剥离和分割:
block_start_marker = pp.AtLineStart("(E")
text_block = (
block_start_marker.suppress()
+ pp.SkipTo(
pp.AtLineStart("E)") | pp.AtLineStart("F)")
)
)
您将获得整个块(包括周围的换行符)的单个结果:
>>> text_block.parse_string("\n".join([
... "(E",
... " This is ",
... " My text block ",
... "E)",
... ]))
ParseResults(['\n This is \n My text block \n'], {})
或者,您可以进行逐行解析,但您只想将解析操作应用于
SkipTo()
元素:
block_end_marker = pp.AtLineStart("E)") | pp.AtLineStart("F)")
text_block = (
block_start_marker.suppress()
+ pp.OneOrMore(
pp.SkipTo("\n").set_parse_action(pp.token_map(str.strip)),
stop_on=block_end_marker
)
)
>>> text_block.parse_string("\n".join([
... "(E",
... " This is ",
... " My text block ",
... "E)",
... ]))
ParseResults(['This is', 'My text block'], {})