我有一个这样的字符串:
a = '{CGPoint={CGPoint=d{CGPoint=dd}}}{CGSize=dd}dd{CSize=aa}'
目前我正在使用此re
语句来获得所需的结果:
filter(None, re.split("\\{(.*?)\\}", a))
但是这给了我:
['CGPoint={CGPoint=d{CGPoint=dd', '}}', 'CGSize=dd', 'dd', 'CSize=aa']
这对我目前的情况不正确,我需要一个这样的列表:
['CGPoint={CGPoint=d{CGPoint=dd}}', 'CGSize=dd', 'dd', 'CSize=aa']
答案 0 :(得分:4)
正如@ m.buettner在评论中指出的那样,Python的正则表达式实现无法匹配嵌套到任意程度的符号对。 (其他语言可以,特别是当前版本的Perl。)当你有正则表达式无法解析的文本时,Pythonic要做的就是使用递归下降解析器。
然而,没有必要通过编写自己的方法重新发明轮子;有很多易于使用的解析库。我建议使用pyparsing,它允许您直接在代码中定义语法,并轻松将操作附加到匹配的令牌。您的代码看起来像这样:
import pyparsing
lbrace = Literal('{')
rbrace = Literal('}')
contents = Word(printables)
expr = Forward()
expr << Combine(Suppress(lbrace) + contents + Suppress(rbrace) + expr)
for line in lines:
results = expr.parseString(line)
答案 1 :(得分:2)
有一个替代的Python正则表达式模块我非常喜欢它支持递归模式: https://pypi.python.org/pypi/regex
pip install regex
然后您可以在正则表达式中使用递归模式,如此脚本中所示:
import regex
from pprint import pprint
thestr = '{CGPoint={CGPoint=d{CGPoint=dd}}}{CGSize=dd}dd{CSize=aa}'
theregex = r'''
(
{
(?<match>
[^{}]*
(?:
(?1)
[^{}]*
)+
|
[^{}]+
)
}
|
(?<match>
[^{}]+
)
)
'''
matches = regex.findall(theregex, thestr, regex.X)
print 'all matches:\n'
pprint(matches)
print '\ndesired matches:\n'
print [match[1] for match in matches]
输出:
all matches:
[('{CGPoint={CGPoint=d{CGPoint=dd}}}', 'CGPoint={CGPoint=d{CGPoint=dd}}'),
('{CGSize=dd}', 'CGSize=dd'),
('dd', 'dd'),
('{CSize=aa}', 'CSize=aa')]
desired matches:
['CGPoint={CGPoint=d{CGPoint=dd}}', 'CGSize=dd', 'dd', 'CSize=aa']
答案 2 :(得分:2)
pyparsing有一个nestedExpr
函数用于匹配嵌套表达式:
import pyparsing as pp
ident = pp.Word(pp.alphanums)
expr = pp.nestedExpr("{", "}") | ident
thestr = '{CGPoint={CGPoint=d{CGPoint=dd}}}{CGSize=dd}dd{CSize=aa}'
for result in expr.searchString(thestr):
print(result)
产量
[['CGPoint=', ['CGPoint=d', ['CGPoint=dd']]]]
[['CGSize=dd']]
['dd']
[['CSize=aa']]
答案 3 :(得分:1)
这是一些伪代码。它会创建一个字符串堆栈,并在遇到紧密支撑时弹出它们。处理遇到的第一个大括号这一事实的一些额外逻辑不包括在数组中。
String source = "{CGPoint={CGPoint=d{CGPoint=dd}}}{CGSize=dd}dd{CSize=aa}";
Array results;
Stack stack;
foreach (match in source.match("[{}]|[^{}]+")) {
switch (match) {
case '{':
if (stack.size == 0) stack.push(new String()); // add new empty string
else stack.push('{'); // child, so include matched brace.
case '}':
if (stack.size == 1) results.add(stack.pop()) // clear stack add to array
else stack.last += stack.pop() + '}"; // pop from stack and concatenate to previous
default:
if (stack.size == 0) results.add(match); // loose text, add to results
else stack.last += match; // append to latest member.
}
}