正如标题所说,以下是一个输入示例:
(outer
(center
(inner)
(inner)
center)
ouer)
(outer
(inner)
ouer)
(outer
ouer)
当然,匹配的字符串将通过递归进行处理。
我希望第一个递归匹配:
[
(outer
(center
(inner)
(inner)
center)
ouer),
(outer
(inner)
ouer),
(outer
ouer)]
之后的过程不用说。。。
我发现了一个简单的正则表达式,它使用递归提取所有嵌套的平衡组,尽管最终的解决方案并不像您预期的那样简单:
正则表达式模式:(1(?:\1??[^1]*?2)
示例输入:1AB1CD1EF22221AB1CD1EF222
为了简单起见,我把1
放在开放括号中,把2
放在封闭括号中。字母字符代表一些内部数据。我将重写输入,以便易于解释。
1 ab 1 cd 1ef2 2 2 1 ab 1 cd 1ef2 2 2
|_1|
|______2__|
|_____________3_____|
在第一次迭代中,正则表达式将匹配第一个兄弟姐妹组中最内部的子组1ef2
1ab1cd1ef222。如果我们记住它和它的位置,并删除这个组,将保留1ab1cd22
。如果我们继续使用正则表达式,它将返回1cd2
,最后返回1ab2
。然后,它将继续以相同的方式解析第二个兄弟姐妹组。
正如我们从这个例子中看到的,正则表达式将正确地提取出出现在括号定义的层次结构中的子串。在第二次迭代中,特定子串在层次结构中的位置将被确定,如果它在字符串中的位置在第二次迭代的子串之间,那么它是一个子节点,否则它是一个兄弟节点。
从我们的例子来看:
>
1ab1cd1ef222 1ab1cd1ef222
,迭代匹配1ef2
,索引6
,
1ab1cd22 1ab1cd1ef222
,迭代匹配1cd2
,索引3
,以6
结尾。因为3
1ab2 1ab1cd1ef222
,迭代匹配1ab2
,索引0
,以3
结尾。因为0
1ab1cd1ef222
,迭代匹配1ef2
,索引6
,因为它不是3
在移到父级之前,我们必须迭代并删除所有兄弟姐妹。因此,我们必须按照迭代中出现的顺序记住所有兄弟姐妹。
不要使用正则表达式。
相反,一个简单的递归函数就足够了。以下是总体结构:
def recursive_bracket_parser(s, i):
while i < len(s):
if s[i] == '(':
i = recursive_bracket_parser(s, i+1)
elif s[i] == ')':
return i+1
else:
# process whatever is at s[i]
i += 1
return i
例如,下面是一个将输入解析为嵌套列表结构的函数:
def parse_to_list(s, i=0):
result = []
while i < len(s):
if s[i] == '(':
i, r = parse_to_list(s, i+1)
result.append(r)
elif s[i] == ')':
return i+1, result
else:
result.append(s[i])
i += 1
return i, result
像这样调用parse_to_list('((a)((b))((c)(d))(efg')
会产生[[['a'],'',[['b']],'',[[c'],['d']],'e','f','g']
的结果。
许多正则表达式实现不允许匹配任意数量的嵌套。然而,Perl、PHP和。NET支持递归模式。
Perl中的演示:
#!/usr/bin/perl -w
my $text = '(outer
(center
(inner)
(inner)
center)
ouer)
(outer
(inner)
ouer)
(outer
ouer)';
while($text =~ /(\(([^()]|(?R))*\))/g) {
print("----------\n$1\n");
}
将打印:
---------- (outer (center (inner) (inner) center) ouer) ---------- (outer (inner) ouer) ---------- (outer ouer)
或者,PHP等价物:
$text = '(outer
(center
(inner)
(inner)
center)
ouer)
(outer
(inner)
ouer)
(outer
ouer)';
preg_match_all('/(\(([^()]|(?R))*\))/', $text, $matches);
print_r($matches);
它产生:
Array ( [0] => Array ( [0] => (outer (center (inner) (inner) center) ouer) [1] => (outer (inner) ouer) [2] => (outer ouer) ) ...
一个解释:
( # start group 1 \( # match a literal '(' ( # group 2 [^()] # any char other than '(' and ')' | # OR (?R) # recursively match the entir pattern )* # end group 2 and repeat zero or more times \) # match a literal ')' ) # end group 1
注意@Goozak的评论:
更好的模式可能是\(?
问题内容: 我正在尝试匹配带有嵌套括号的类似数学表达式的字符串。 [‘((((1 + 0)+1)+1)’] 我希望它与所有包含的表达式匹配,例如(1 + 0),((1 + 0)+1)… 我什至不在乎它是否匹配不需要的表达式,例如(((1 + 0),我可以照顾的。 为什么它还没有这样做,我该怎么做? 问题答案: 正则表达式尝试匹配尽可能多的文本,从而消耗了所有字符串。它不会在字符串的一部分上寻找正则
我有这样一个文本: 我试图在c#中使用正则表达式来提取嵌套的if/eles-段。 要查找“?”,我使用了: 模式1: 找到“:”我用了: 模式2:
我正在寻找一个正则表达式(**),它将匹配未知数量的嵌套函数。所以 所有的比赛都会成功。但举例来说,如果我在末尾添加一个额外的结束括号,它将不会包含在比赛中。 (**)请不要回答通过解析(和计算括号)比使用正则表达式更容易做到这一点——在挠头一会儿后,我已经知道了!
问题内容: 我正在尝试编写一个匹配嵌套括号的正则表达式,例如: 这样的字符串应该匹配,导致所有嵌套括号都被关闭,而是: 不应该或更好地至少匹配第一个“(((text)))(text)”部分。 实际上,我的正则表达式是: 但这并不能像我期望的那样正常工作。如何解决?我哪里错了?谢谢! 问题答案: 当我找到此答案时,我无法弄清楚如何修改模式以使用自己的定界符where 和。所以我的方法是使其更通用。
问题内容: 匹配字符串中的’(’的正则表达式是什么? 以下是场景: 我有一串 我想使用正则表达式拆分字符串。为此,我正在使用 但是我收到以下异常。 转义似乎不起作用。 问题答案: 两种选择: 首先,你可以使用转义 回 斜线- 另外,由于它是单个字符,因此您可以将其放入不需要转义的字符类中-
问题内容: 我一直试图在Java中编写一个正则表达式以删除下面括号中的所有内容,同时保留其他所有内容。 注意,括号可以嵌套,这就是为什么我的模式失败的原因 。有人能帮我吗?下面我试过了: 但这打印: d4 Nf6 2. c4 g6 3. Nc3 Bg7 4. e4 d6 5. Nf3 OO 6. Be2 e5 7. dxe5 dxe5 8. Qxd8 Rxd8 9. Bg5 Nbd7 10. OO