3

我有一个这样的字符串:

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

4 回答 4

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)
于 2013-07-01T14:46:39.260 回答
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']
于 2013-07-01T15:50:36.010 回答
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']]
于 2013-07-01T21:29:45.253 回答
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.
    }
}
于 2013-07-01T14:37:30.753 回答