我需要一个正则表达式来选择两个外括号之间的所有文本.
例: some text(text here(possible text)text(possible text(more text)))end text
结果: (text here(possible text)text(possible text(more text)))
Fra*_*ank 131
正则表达式是工作的错误工具,因为您正在处理嵌套结构,即递归.
但是有一个简单的算法可以做到这一点,我在前一个问题的答案中对此进行了描述.
rog*_*111 110
你可以使用正则表达式递归:
\(([^()]|(?R))*\)
Run Code Online (Sandbox Code Playgroud)
bob*_*ble 107
我想添加这个答案以便快速参考.随意更新.
.NET Regex使用平衡组.
\((?>\((?<c>)|[^()]+|\)(?<-c>))*(?(c)(?!))\)
Run Code Online (Sandbox Code Playgroud)
在哪里c用作深度计数器.
PCRE使用递归模式.
\((?:[^)(]+|(?R))*+\)
Run Code Online (Sandbox Code Playgroud)
在regex101演示 ; 或者没有替换:
\((?:[^)(]*(?R)?)*+\)
Run Code Online (Sandbox Code Playgroud)
在regex101演示 ; 或展开性能:
\([^)(]*+(?:(?R)[^)(]*)*+\)
Run Code Online (Sandbox Code Playgroud)
在regex101演示 ; 粘贴的图案(?R)代表(?0).
的Perl,PHP,记事本++, - [R :perl的= TRUE,Python的:正则表达式包与(?V1)为Perl行为.
Ruby使用子表达式调用.
使用Ruby 2.0 \g<0>可以用来调用完整模式.
\((?>[^)(]+|\g<0>)*\)
Run Code Online (Sandbox Code Playgroud)
在Rubular演示 ; Ruby 1.9仅支持捕获组递归:
(\((?>[^)(]+|\g<1>)*\))
Run Code Online (Sandbox Code Playgroud)
JavaScript API :: XRegExp.matchRecursive
XRegExp.matchRecursive(str, '\\(', '\\)', 'g');
Run Code Online (Sandbox Code Playgroud)
JS,Java和其他正则表达式,没有递归,最多可达2级嵌套:
\((?:[^)(]+|\((?:[^)(]+|\([^)(]*\))*\))*\)
Run Code Online (Sandbox Code Playgroud)
在regex101演示.需要将更深的嵌套添加到模式中.
要在不平衡的括号上更快地失败,请丢弃+量词.
Java:使用@jaytea的前向引用有趣的想法.
Zac*_*ena 28
[^\(]*(\(.*\))[^\)]*
Run Code Online (Sandbox Code Playgroud)
[^\(]*匹配字符串开头不是(\(.*\))左括号的[^\)]*所有内容,捕获括在括号中的所需子字符串,并匹配字符串末尾不是右括号的所有内容.请注意,此表达式不会尝试匹配括号; 一个简单的解析器(参见dehmann的答案)会更适合它.
Tom*_*lak 17
(?<=\().*(?=\))
Run Code Online (Sandbox Code Playgroud)
如果要在两个匹配的括号中选择文本,则表示您对正则表达式不满意.这是不可能的(*).
此正则表达式只返回字符串中第一个开头和最后一个右括号之间的文本.
(*)除非您的正则表达式引擎具有平衡组或递归等功能.支持此类功能的引擎数量正在缓慢增长,但它们仍然不常用.
Ale*_*osh 12
实际上可以使用.NET正则表达式来完成它,但它并不是微不足道的,所以请仔细阅读.
你可以在这里阅读一篇好文章.您还可能需要阅读.NET正则表达式.你可以在这里开始阅读.
<>使用尖括号是因为它们不需要转义.
正则表达式如下所示:
<
[^<>]*
(
(
(?<Open><)
[^<>]*
)+
(
(?<Close-Open>>)
[^<>]*
)+
)*
(?(Open)(?!))
>
Run Code Online (Sandbox Code Playgroud)
mus*_*ibs 12
这个答案解释了为什么正则表达式不是执行此任务的正确工具的理论限制。
正则表达式不能做到这一点。
正则表达式基于称为的计算模型Finite State Automata (FSA)。顾名思义,a FSA只能记住当前状态,而没有关于先前状态的信息。
在上图中,S1和S2是两个状态,其中S1是开始步骤和最终步骤。因此,如果我们尝试使用字符串0110,则转换如下:
0 1 1 0
-> S1 -> S2 -> S2 -> S2 ->S1
Run Code Online (Sandbox Code Playgroud)
在上述步骤中,当我们处于第二个位置时,S2即在解析01之后0110,FSA没有关于前一个输入的信息0,01因为它只能记住当前状态和下一个输入符号。
在上述问题中,我们需要知道开括号的编号;这意味着它必须存储在某个地方。但是由于FSAs不能做到这一点,所以不能编写正则表达式。
但是,可以编写算法来完成此任务。算法通常属于Pushdown Automata (PDA)。PDA是的上一级FSA。PDA有一个额外的堆栈来存储一些其他信息。PDA可用于解决上述问题,因为我们可以push在堆栈中“打开括号pop”,并在遇到闭合括号时“”。如果最后堆栈是空的,则打开括号和关闭括号匹配。否则不行。
这是最终的正则表达式:
\(
(?<arguments>
(
([^\(\)']*) |
(\([^\(\)']*\)) |
'(.*?)'
)*
)
\)
Run Code Online (Sandbox Code Playgroud)
例子:
input: ( arg1, arg2, arg3, (arg4), '(pip' )
output: arg1, arg2, arg3, (arg4), '(pip'
Run Code Online (Sandbox Code Playgroud)
请注意,'(pip'是作为字符串正确管理的。(在监管机构中尝试:http : //sourceforge.net/projects/regulator/)
我也陷入了嵌套模式出现的这种情况。
正则表达式是解决上述问题的正确方法。使用下面的模式
'/(\((?>[^()]+|(?1))*\))/'
Run Code Online (Sandbox Code Playgroud)
小智 5
使用Ruby的正则表达式(1.9.3或以上版本):
/(?<match>\((?:\g<match>|[^()]++)*\))/
Run Code Online (Sandbox Code Playgroud)
我编写了一个名为Balanced 的小型 JavaScript 库来帮助完成此任务。你可以通过这样做来完成这个任务
balanced.matches({
source: source,
open: '(',
close: ')'
});
Run Code Online (Sandbox Code Playgroud)
您甚至可以进行替换:
balanced.replacements({
source: source,
open: '(',
close: ')',
replace: function (source, head, tail) {
return head + source + tail;
}
});
Run Code Online (Sandbox Code Playgroud)
这是一个更复杂且交互式的示例JSFiddle。
除了bobble bubble 的答案之外,还有其他支持递归构造的正则表达式风格。
\n卢阿
\n使用%b()(%b{}/%b[]代表大括号/方括号):
for s in string.gmatch("Extract (a(b)c) and ((d)f(g))", "%b()") do print(s) end(参见演示)Raku(以前的 Perl6):
\n非重叠的多个平衡括号匹配:
\nmy regex paren_any { \'(\' ~ \')\' [ <-[()]>+ || <&paren_any> ]* }\nsay "Extract (a(b)c) and ((d)f(g))" ~~ m:g/<&paren_any>/;\n# => (\xef\xbd\xa2(a(b)c)\xef\xbd\xa3 \xef\xbd\xa2((d)f(g))\xef\xbd\xa3)\nRun Code Online (Sandbox Code Playgroud)\n重叠多个平衡括号匹配:
\nsay "Extract (a(b)c) and ((d)f(g))" ~~ m:ov:g/<&paren_any>/;\n# => (\xef\xbd\xa2(a(b)c)\xef\xbd\xa3 \xef\xbd\xa2(b)\xef\xbd\xa3 \xef\xbd\xa2((d)f(g))\xef\xbd\xa3 \xef\xbd\xa2(d)\xef\xbd\xa3 \xef\xbd\xa2(g)\xef\xbd\xa3)\nRun Code Online (Sandbox Code Playgroud)\n请参阅演示。
\nPythonre非正则表达式解决方案
请参阅poke's 答案How to get an expression Between Balanced Parentheses。
\nJava可定制的非正则表达式解决方案
\n这是一个可定制的解决方案,允许在 Java 中使用单字符文字分隔符:
\npublic static List<String> getBalancedSubstrings(String s, Character markStart, \n Character markEnd, Boolean includeMarkers) \n\n{\n List<String> subTreeList = new ArrayList<String>();\n int level = 0;\n int lastOpenDelimiter = -1;\n for (int i = 0; i < s.length(); i++) {\n char c = s.charAt(i);\n if (c == markStart) {\n level++;\n if (level == 1) {\n lastOpenDelimiter = (includeMarkers ? i : i + 1);\n }\n }\n else if (c == markEnd) {\n if (level == 1) {\n subTreeList.add(s.substring(lastOpenDelimiter, (includeMarkers ? i + 1 : i)));\n }\n if (level > 0) level--;\n }\n }\n return subTreeList;\n }\n}\nRun Code Online (Sandbox Code Playgroud)\n使用示例:
\nString s = "some text(text here(possible text)text(possible text(more text)))end text";\nList<String> balanced = getBalancedSubstrings(s, \'(\', \')\', true);\nSystem.out.println("Balanced substrings:\\n" + balanced);\n// => [(text here(possible text)text(possible text(more text)))]\nRun Code Online (Sandbox Code Playgroud)\n
| 归档时间: |
|
| 查看次数: |
317506 次 |
| 最近记录: |