我想知道我在这里做错了什么。也许有人可以给我一个关于这个问题的暗示。
我想使用以字符串_Init
终止的pyparsing来检测某些令牌。
例如,我在text
one
two_Init
threeInit
four_foo_Init
five_foo_bar_Init
我想提取以下几行:
two_Init
four_foo_Init
five_foo_bar_Init
目前,我已将问题简化为以下几行:
import pyparsing as pp
ident = pp.Word(pp.alphas, pp.alphanums + "_")
ident_init = pp.Combine(ident + pp.Literal("_Init"))
for detected, s, e in ident_init.scanString(text):
print detected
使用此代码没有结果。如果我删除"_"
语句中的Word
,那么我至少可以检测到其末尾有_Init
的行。但结果并不完整:
['two_Init']
['foo_Init']
['bar_Init']
有人有任何想法,我在这里完全错了吗?
答案 0 :(得分:2)
问题是,只要不是终止“_
”中的“_
”,您就会接受“_Init
”。这里有两个pyparsing解决方案,一个是更“纯粹”的pyparsing,另一个只是用它来说它并使用嵌入式正则表达式。
samples = """\
one
two_Init
threeInit
four_foo_Init
six_seven_Init_eight_Init
five_foo_bar_Init"""
from pyparsing import Combine, OneOrMore, Word, alphas, alphanums, Literal, WordEnd, Regex
# implement explicit lookahead: allow '_' as part of your Combined OneOrMore,
# as long as it is not followed by "Init" and the end of the word
option1 = Combine(OneOrMore(Word(alphas,alphanums) |
'_' + ~(Literal("Init")+WordEnd()))
+ "_Init")
# sometimes regular expressions and their implicit lookahead/backtracking do
# make things easier
option2 = Regex(r'\b[a-zA-Z_][a-zA-Z0-9_]*_Init\b')
for expr in (option1, option2):
print '\n'.join(t[0] for t in expr.searchString(samples))
print
两个选项都打印出来:
two_Init
four_foo_Init
six_seven_Init_eight_Init
five_foo_bar_Init