正则表达式:非贪婪与堆栈?

时间:2011-09-14 23:28:14

标签: regex

我必须在LaTeX和HTML文件中做很多regex ..而且我常常在以下情况下找到自己:

我想要将\mbox{\sqrt{2}} + \sqrt{4}这样的内容剥离到\sqrt{2} + \sqrt{4}。 用文字表示:“用其内容替换每次出现的\ mbox {...}。

那么,我该怎么做?

贪婪的版本\mbox{(.*)}让我{1}获得1美元的奖金 非贪婪版本\sqrt{2}} + \sqrt{4以1美元的价格获得\mbox{(.*?)}

两者都不是我想要的。

我需要的是,RegEx引擎保持某种程度 位于\sqrt{2之前和之后的位置的字符堆栈,即(.*){。因此,当}中遇到新的{时,它应该放在堆栈上。遇到.*时,应从堆栈中删除最后一个}。当堆栈为空时,{完成。

嵌套HTML标签也会出现类似情况。

因此,由于大多数正则表达式引擎为每个正则表达式创建一个FSA,堆栈应该是可行的,还是我错过了什么?一些我不知道的罕见修饰语?我想知道,为什么没有解决方案。

当然我可以使用java / python / perl为我自己编写一些东西..但是我想将它集成在RegEx中:)

问候,吉尔伯特

(ps:我省略了项目.*以保持示例小,+ \sqrt{4}也应该转义)

3 个答案:

答案 0 :(得分:2)

这取决于您的正则表达式引擎,但是.Net正则表达式引擎可以如下...

\\mbox{(
    (?>
        [^{}]+ 
        |   { (?<number>)
        |   } (?<-number>)
    )*
    (?(number)(?!))
)
}

假设您使用的是IgnorePatternWhiteSpace

然后,您可以regex.Replace(sourceText,"$1")执行您希望的转换

答案 1 :(得分:1)

这是另一个适用于perl http://codepad.org/fcVz9Bky的正则表达式:

s/
\\mbox{
  (
    (?:
      [^{}]+     #either match any number of non-braces
      |          #or
      \{[^{}]+}  #braces surrounding non-braces
    )*
  )
}
/$1/x;

注意:它仅适用于一个嵌套级别

答案 2 :(得分:1)

您可以使用的另一个技巧是递归正则表达式(应该由PCRE和其他一些版本支持):

\\mbox(\{([^{}]|(?1)+)*+\})

如果你处于正确的心态,不要太多解释 这是一个类似的,但更灵活一些(例如,更容易添加[](),或其他平衡结构):

\\mbox\{([^{}]|\{(?1)*\})*\}