p = r'(<>)+'
for _ in range(4):
# p = r'(<>|<p>)+'.replace('p', p)
p = r'(<(p)?>)+'.replace('p', p)
pattern = p.replace('<', r'\(').replace('>', r'\)')
print(p)
print(pattern)
测试它:
import re
good = "()()()", "((((()))))", "(()((()))())"
bad = "())()", "(((((())))))", "(x)"
for s in good:
print(re.fullmatch(pattern, s))
for s in bad:
print(re.fullmatch(pattern, s))
3条答案
按热度按时间fdbelqdn1#
除非它必须是一个表达式,否则可以使用多个re.sub将“()”替换为空字符串五次。如果所有括号匹配到5级深度,则应该得到一个空字符串:
输出:
如果你需要一个表达式,你可以在一个循环(嵌套)模式中嵌套多个非捕获组,期望一个开始括号,一个重复0-n次的有效配对,然后是一个结束括号。使外部组至少重复一次并跨越整个字符串(
^(
...)+$
):循环模式是
\((?:
...)*\)
,您将其嵌套在其内部5层深,以\(\)
结尾,用于最内部的匹配括号。请注意,非捕获组只是为了避免在match对象中获得多个条目。由于您只查找True/False,而不是提取的字符串本身,因此它可能也适用于捕获组:
r"^(\((\((\((\((\(\))*\))*\))*\))*\))+$"
hi3rlvi22#
这里有两个解决方案,用于平衡
<
和>
,因为它更容易读取/写入:同样,但
<
和>
替换为\(
和\)
:我从深度1的模式开始构建它们,然后使用它构建深度1到2的模式,然后使用它构建深度1到3的模式,依此类推,直到5:
测试它:
测试结果(Attempt This Online!):
ha5z0ras3#
一个较短的模式找到了一个不同的方式比我的第一个答案:
首先,我写了一个DFA(使用
a
和b
代替括号):si
是初始状态,se
是错误状态,s0
到s5
表示当前打开了多少个括号(0到5)。该图像是在我输入此DFA时由FSM2Regex创建的:
它也给了我这个模式:
注意,
$
表示那里的空字符串,+
表示交替。它没有使用+
表示“前面的一个或多个”,所以我在看到这个答案后,自己在这个答案的顶部写了一个短模式。