当前位置:  开发笔记 > 编程语言 > 正文

正则表达式匹配外括号

如何解决《正则表达式匹配外括号》经验,为你挑选了7个好方法。

我需要一个正则表达式来选择两个外括号之间的所有文本.

例: some text(text here(possible text)text(possible text(more text)))end text

结果: (text here(possible text)text(possible text(more text)))



1> Frank..:

正则表达式是工作的错误工具,因为您正在处理嵌套结构,即递归.

但是有一个简单的算法可以做到这一点,我在前一个问题的答案中对此进行了描述.


我不同意正则表达式是错误的工具,原因有几个.1)大多数正则表达式实现都有一个可行但如果不是完美的解决方案.2)通常,你试图在一个上下文中找到平衡的分隔符对,其中也适用于正则表达式的其他标准.3)通常你将正则表达式交给一些只接受正则表达式的API,你别无选择.
正则表达式是这项工作的正确工具.这个答案是对的.请参阅rogal111的回答.
.NET的实现有[平衡组定义http://msdn.microsoft.com/en-us/library/bs2twtah.aspx#balancing_group_definition]允许这种事情.
绝对同意答案.虽然在regexp中有一些递归的实现,但它们等于有限状态机,并且不支持使用嵌套结构,但Context Free Grammars会这样做.看看霍姆斯基的正式语法的层次结构.

2> rogal111..:

你可以使用正则表达式递归:

\(([^()]|(?R))*\)


在.NET 4.5中,我得到以下错误:"无法识别的分组构造".
@AndyHayden这是因为“(1,(2,3))(4,5)”有两个用空格隔开的组。将我的正则表达式与全局标志一起使用:/ \(([[((^()] ||(?R))* \)/ g。这是在线测试:http://regex101.com/r/lF0fI1/1
一个例子在这里真的很有用,我不能让它适用于像"(1,(2,3))(4,5)"这样的东西.
真棒!这是正则表达式的一个很好的特性.感谢您是唯一真正回答这个问题的人.此外,regex101网站很甜蜜.

3> bobble bubbl..:

我想添加这个答案以便快速参考.随意更新.


.NET Regex使用平衡组.

\((?>\((?)|[^()]+|\)(?<-c>))*(?(c)(?!))\)

在哪里c用作深度计数器.

在Regexstorm.com上演示

堆栈溢出:使用RegEx平衡匹配括号

Wes'令人费解的博客:使用.NET正则表达式匹配平衡构造

Greg Reinacker的博客:正则表达式中的嵌套构造


PCRE使用递归模式.

\((?:[^)(]+|(?R))*+\)

在regex101演示 ; 或者没有替换:

\((?:[^)(]*(?R)?)*+\)

在regex101演示 ; 或展开性能:

\([^)(]*+(?:(?R)[^)(]*)*+\)

在regex101演示 ; 粘贴的图案(?R)代表(?0).

的Perl,PHP,记事本++, - [R :perl的= TRUE,Python的:正则表达式包与(?V1)为Perl行为.


Ruby使用子表达式调用.

使用Ruby 2.0 \g<0>可以用来调用完整模式.

\((?>[^)(]+|\g<0>)*\)

在Rubular演示 ; Ruby 1.9仅支持捕获组递归:

(\((?>[^)(]+|\g<1>)*\))

Rubular演示  (Ruby 1.9.3以来的原子分组)


JavaScript  API :: XRegExp.matchRecursive

XRegExp.matchRecursive(str, '\\(', '\\)', 'g');

JS,Java和其他正则表达式,没有递归,最多可达2级嵌套:

\((?:[^)(]+|\((?:[^)(]+|\([^)(]*\))*\))*\)

在regex101演示.需要将更深的嵌套添加到模式中.
要在不平衡的括号上更快地失败,请丢弃+量词.


Java:使用@jaytea的前向引用有趣的想法.


参考 - 这个正则表达式意味着什么?

rexegg.com - 递归正则表达式

Regular-Expressions.info - 正则表达式递归


最佳答案,谢谢您的研究!

4> Zach Scriven..:
[^\(]*(\(.*\))[^\)]*

[^\(]*匹配字符串开头不是(\(.*\))左括号的[^\)]*所有内容,捕获括在括号中的所需子字符串,并匹配字符串末尾不是右括号的所有内容.请注意,此表达式不会尝试匹配括号; 一个简单的解析器(参见dehmann的答案)会更适合它.


这个expr不能像"text(text)text(text)text"返回"(text)text(text)"这样的东西.正则表达式不能计算括号.

5> Tomalak..:
(?<=\().*(?=\))

如果要在两个匹配的括号中选择文本,则表示您对正则表达式不满意.这是不可能的(*).

此正则表达式只返回字符串中第一个开头和最后一个右括号之间的文本.


(*)除非您的正则表达式引擎具有平衡组递归等功能.支持此类功能的引擎数量正在缓慢增长,但它们仍然不常用.


@ghayes答案是从2009年开始的.那是*很久以前的事了; 允许某种形式的递归的正则表达式引擎比现在更常见(并且它们*仍然非常罕见).我会在答案中提到它.

6> Alexander Ba..:

实际上可以使用.NET正则表达式来完成它,但它并不是微不足道的,所以请仔细阅读.

你可以在这里阅读一篇好文章.您还可能需要阅读.NET正则表达式.你可以在这里开始阅读.

<>使用尖括号是因为它们不需要转义.

正则表达式如下所示:

<
[^<>]*
(
    (
        (?<)
        [^<>]*
    )+
    (
        (?>)
        [^<>]*
    )+
)*
(?(Open)(?!))
>



7> musibs..:

这个答案解释了为什么正则表达式不是执行此任务的正确工具的理论限制。


正则表达式不能做到这一点。

正则表达式基于称为的计算模型Finite State Automata (FSA)。顾名思义,a FSA只能记住当前状态,而没有关于先前状态的信息。

在上图中,S1和S2是两个状态,其中S1是开始步骤和最终步骤。因此,如果我们尝试使用字符串0110,则转换如下:

      0     1     1     0
-> S1 -> S2 -> S2 -> S2 ->S1

在上述步骤中,当我们处于第二个位置时,S2即在解析01之后0110,FSA没有关于前一个输入的信息001因为它只能记住当前状态和下一个输入符号。

在上述问题中,我们需要知道开括号的编号;这意味着它必须存储在某个地方。但是由于FSAs不能做到这一点,所以不能编写正则表达式。

但是,可以编写算法来完成此任务。算法通常属于Pushdown Automata (PDA)PDA是的上一级FSA。PDA有一个额外的堆栈来存储一些其他信息。PDA可用于解决上述问题,因为我们可以push在堆栈中“打开括号pop”,并在遇到闭合括号时“”。如果最后堆栈是空的,则打开括号和关闭括号匹配。否则不行。

推荐阅读
凹凸曼00威威_694
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有