使用pyparsing在多行上捕获块



尝试解析多行文档上的多个选择。想要捕获每个关键字之间的所有行。下面是一个示例:

Keyword 1: CAPTURE THIS TEXT
Keyword 2: CAPTURE THIS TEXT
Keyword 3:
CAPTURE THIS TEXT
CAPTURE THIS TEXT
CAPTURE THIS TEXT
Keyword 4

我也可能有

Keyword 1: CAPTURE THIS TEXT
CAPTURE THIS TEXT
Keyword 2: CAPTURE THIS TEXT
Keyword 3:
CAPTURE THIS TEXT
CAPTURE THIS TEXT
CAPTURE THIS TEXT
CAPTURE THIS TEXT
Keyword 4

我的代码看起来像

from pyparsing import *
EOL = LineEnd().suppress()
line = OneOrMore(Group(SkipTo(LineEnd()) + EOL))
KEYWORD_CAPTURE_AREA = Keyword("Keyword 1:").suppress() + line + Keyword("Keyword 2:").suppress() + line 
+ Keyword("Keyword 3:").suppress() + line + Keyword("Keyword 4").suppress()

如果我的结果跨越多行,当前方法不会返回任何结果。假设应该有一个简单的解决方案——只是还没有找到。

使用pyparsing学习的概念是每个子表达式独立运行,不知道任何包含或跟随的表达式。因此,当您line要匹配一个或多个"跳到当前行的末尾"时,它不知道当它看到下一个"关键字"字符串时应该停止,因此它可以预见地读取到字符串的末尾。然后,当解析器继续查找"关键字 2:"时,它已经远远超过了该点,因此会引发异常。

您需要告诉OneOrMore,如果它在一行的开头找到"关键字",它应该停止解析,即使这通常与重复表达式匹配。如果在行首找到"关键字"一词,则对块末尾的合理检测可能是单词"关键字"。(你可以让它更详细,并匹配"Keyword" + integer + ":",使它真正防弹。我们称之为"start_of_block_marker":

start_of_block_marker = LineStart() + "Keyword"

若要告诉 OneOrMore 这表示其重复的停止条件,请将此表达式作为stopOn参数传递:

line = OneOrMore(Group(SkipTo(LineEnd()) + EOL), 
stopOn=LineStart() + "Keyword")

现在这将解析您的所有字符串,但是您正在OneOrMore中进行分组,而我认为您真的希望将所有子字符串放在一个组中。此外,2 和 3 之间的空行会创建一个额外的空行。这是行的改进版本:

line = Optional(EOL) + Group(OneOrMore(SkipTo(LineEnd()) + EOL,
stopOn=LineStart() + "Keyword"))

我把你的两个测试字符串放在一个列表中,然后用它作为参数来runTests()

text1 = """
Keyword 1: CAPTURE THIS TEXT
CAPTURE THIS TEXT
Keyword 2: CAPTURE THIS TEXT
Keyword 3:
CAPTURE THIS TEXT
CAPTURE THIS TEXT
CAPTURE THIS TEXT
CAPTURE THIS TEXT
Keyword 4"""
text2 = """
Keyword 1: CAPTURE THIS TEXT
Keyword 2: CAPTURE THIS TEXT
Keyword 3:
CAPTURE THIS TEXT
CAPTURE THIS TEXT
CAPTURE THIS TEXT
Keyword 4
"""
KEYWORD_CAPTURE_AREA.runTests(tests)

哪些打印(回显每个测试,然后打印解析的结果):

Keyword 1: CAPTURE THIS TEXT
CAPTURE THIS TEXT
Keyword 2: CAPTURE THIS TEXT
Keyword 3:
CAPTURE THIS TEXT
CAPTURE THIS TEXT
CAPTURE THIS TEXT
CAPTURE THIS TEXT
Keyword 4
[['CAPTURE THIS TEXT', 'CAPTURE THIS TEXT'], ['CAPTURE THIS TEXT'], ['CAPTURE THIS TEXT', 'CAPTURE THIS TEXT', 'CAPTURE THIS TEXT', 'CAPTURE THIS TEXT']]
[0]:
['CAPTURE THIS TEXT', 'CAPTURE THIS TEXT']
[1]:
['CAPTURE THIS TEXT']
[2]:
['CAPTURE THIS TEXT', 'CAPTURE THIS TEXT', 'CAPTURE THIS TEXT', 'CAPTURE THIS TEXT']

Keyword 1: CAPTURE THIS TEXT
Keyword 2: CAPTURE THIS TEXT
Keyword 3:
CAPTURE THIS TEXT
CAPTURE THIS TEXT
CAPTURE THIS TEXT
Keyword 4
[['CAPTURE THIS TEXT'], ['CAPTURE THIS TEXT'], ['CAPTURE THIS TEXT', 'CAPTURE THIS TEXT', 'CAPTURE THIS TEXT']]
[0]:
['CAPTURE THIS TEXT']
[1]:
['CAPTURE THIS TEXT']
[2]:
['CAPTURE THIS TEXT', 'CAPTURE THIS TEXT', 'CAPTURE THIS TEXT']

如果结果中存在错误,runTests()将显示问题行和位置,并给出pyparsing错误消息。

它必须是pyparsing吗?

如果没有,您可以使用拆分,例如

f = open('sample.txt')
values = []
for text in f.read().split('Keyword '):
values.append(text[2:])
print(values)
>> ['', ' CAPTURE THIS TEXTn           CAPTURE THIS TEXTn', ' CAPTURE THIS TEXTnn', 'nCAPTURE THIS TEXTnCAPTURE THIS TEXTnCAPTURE THIS TEXTnCAPTURE THIS TEXTnn', '']

最新更新