【发布时间】:2013-07-02 23:59:42
【问题描述】:
我需要一种方法,在 python 中给出一个文本字符串,将其内容分成一个列表,按 3 个参数分割 - 最外面的括号与最外面的括号与普通文本,保留原始语法。
例如,给定一个字符串
(([a] b) c ) [d] (e) f
预期的输出将是这个列表:
['(([a] b) c )', '[d]', '(e)', ' f']
我用正则表达式尝试了几件事,例如
\[.+?\]|\(.+?\)|[\w+ ?]+
这给了我
>>> re.findall(r'\[.+?\]|\(.+?\)|[\w+ ?]+', '(([a] b) c ) [d] (e) f')
['(([a] b)', ' c ', ' ', '[d]', ' ', '(e)', ' f']
(错误列表中的项目c)
我也试过贪心版的,
\[.+\]|\(.+\)|[\w+ ?]+
但是当字符串具有相同类型的单独运算符时它就不足了:
>>> re.findall(r'\[.+\]|\(.+\)|[\w+ ?]+', '(([a] b) c ) [d] (e) f')
['(([a] b) c ) [d] (e)', ' f']
然后我从正则表达式转而使用堆栈:
>>> def parenthetic_contents(string):
stack = []
for i, c in enumerate(string):
if c == '(' or c == '[':
stack.append(i)
elif (c == ')' or c == ']'):
start = stack.pop()
yield (len(stack), string[start + 0:i+1])
对于方括号和圆括号来说效果很好,除了我无法获得平面文本(或者我有,但我不知道?):
>>> list(parenthetic_contents('(([a] b) c ) [d] (e) f'))
[(2, '[a]'), (1, '([a] b)'), (0, '(([a] b) c )'), (0, '[d]'), (0, '(e)')]
我不熟悉 pyparsing。起初它看起来好像 nestedExpr() 可以解决问题,但它只需要一个分隔符(() 或 [],但不能同时使用两者),这对我不起作用。
我现在完全没有想法了。欢迎提出任何建议。
【问题讨论】:
-
作为一般规则,正则表达式不能为您匹配括号,因为它们不“计数”(按原样)打开和关闭项目。这与pushdown automaton 从根本上比finite state machine 更强大有关。更多:princeton.edu/~achaney/tmve/wiki100k/docs/…
标签: python regex stack pyparsing