Python中的正则表达式花括号

时间:2013-07-01 14:09:30

标签: python regex

我有一个这样的字符串:

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']

4 个答案:

答案 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.
    }
}