正则表达式提取嵌套模式

时间:2013-02-05 16:21:18

标签: python regex python-3.x

  

可能重复:
  Matching Nested Structures With Regular Expressions in Python

我无法解决这个问题。我有一个类似下面的字符串:

Lorem ipsum dolor sit amet [@a xxx yyy [@b xxx yyy [@c xxx yyy]]] lorem ipsum sit amet

我的任务是提取命令(它们始终以 [@ 开头,以] 结尾)及其子命令。像

这样的结果
[
    [@a xxx yyy [@b xxx yyy [@c xxx yyy]]], # the most outer
    [@b xxx yyy [@c xxx yyy]],              # the middle one
    [@c xxx yyy]                            # the inner most
]

将受到高度赞赏。问题是这些命令可以在非常长的文本消息中发生,因此“高性能”的解决方案会很好。

我正在玩弄一些正则表达模式,大多数情况下是

(\[@.*?\]\s) # for the outer one

但我没有看到匹配中间和内部的光。为了使它更复杂,嵌套命令的数量是可变的...... 一些特殊的正则表达式可能是解决方案吗?我已经阅读过关于前瞻和后视的内容,但不知道如何在这种特殊情况下使用它们。

感谢一帮!

更新

@ Cyborgx37向我指出另一个使用pyparsing包的帖子。没有外部包或库的解决方案会很好。但是,pyparsing肯定能解决这个问题!

3 个答案:

答案 0 :(得分:2)

C#具有递归/嵌套的RegEx,我不相信Python会这样做。您可以在以前的结果上重新运行RegEx搜索,但这可能效率低(RegEx用于这种简单搜索的开销),而不仅仅是制作自定义解析器。您搜索“[@”和“]”的文字并不复杂。

这是一个可以完成这项工作的自定义解析器(在JavaScript中)。

var txt = "Lorem ipsum dolor sit amet [@a xxx yyy [@b xxx yyy [@c xxx yyy]]] lorem ipsum sit amet";
function parse(s) {
    var stack = [];
    var result = [];
    for(var x=0; x<s.length; x++) {
        var c = s.charAt(x);
        if(c == '[' && x+1 < s.length-1 && s.charAt(x+1) == '@') {
            for(var y=0; y<stack.length; y++)
                stack[y] += "[@";
            stack.push("[@");
            x++;
        } else if(c == ']' && stack.length > 0) {
            for(var y=0; y<stack.length; y++)
                stack[y] += "]";
            result.push(stack.pop());
        } else {
            for(var y=0; y<stack.length; y++)
                stack[y] += c;
        }
    }
    return result;
}
parse(txt);

它快速遍历文本的所有字符(仅一次)并使用堆栈和if ... if else ... else条件分别推送,弹出和修改该堆栈中的值。

答案 1 :(得分:0)

所以来自ac #background,我不确定这会帮助但是,我想,既然你必须解析内部命令,为什么不只是存储内容命令,然后再次对内部数据运行你的正则表达式函数?我知道我可能错过了一些东西,但这就是为什么我会尝试至少。

答案 2 :(得分:0)

难怪你无法解决这个问题。有关正式语言的正式语言理论。 Noam Chomsky描述了四种语言 - 称为Chomsky hierarchy。正则表达式能够描述语言的简易类别 - 常规语言。但是,具有嵌套配对结构的语言不在常规语言中,并且正则表达式无法描述/接受它们。

一种最容易实现的解析器是基于递归调用解析语言元素的函数的解析器。