如何从字符串中的外部括号中删除所有文本?

2024-05-15 23:21:33 发布

您现在位置:Python中文网/ 问答频道 /正文

当我有一根这样的绳子时:

s1 = 'stuff(remove_me)'

我可以使用

# returns 'stuff'
res1 = re.sub(r'\([^)]*\)', '', s1)

here所述。

但我有时会遇到这样的嵌套表达式:

s2 = 'stuff(remove(me))'

当我从上面运行命令时

'stuff)'

我也试过:

re.sub('\(.*?\)', '', s2)

给我同样的输出。

如何删除外圆括号中的所有内容(包括圆括号本身),以便最终也得到'stuff'(对于任意复杂的表达式应该是这样的)?


Tags: 命令re内容here表达式removereturnsme
3条回答

re对于您提到的简单测试用例,只需让regex运行,匹配就非常迫切,因此它们会尽可能多地匹配文本:

>>> re.sub(r'\(.*\)', '', 'stuff(remove(me))')
'stuff'

如前所述,您需要一个recursive regex来匹配任意级别的嵌套,但如果您知道最多只能有一个级别的嵌套,请尝试使用此模式:

\((?:[^)(]|\([^)(]*\))*\)
  • [^)(]匹配的字符不是括号(negated class)。
  • |\([^)(]*\)或者它与另一个()对匹配,其中有任意数量的non)(
  • (?:)*所有这些在()内任意次数

Here is a demo at regex101

在交替使用[^)(]而不使用+量词之前,如果不平衡,则会更快地失败。
您需要添加更多可能发生的嵌套级别。例如,最高2级:

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

Another demo at regex101

注意\(.*\)匹配左边的第一个(,然后匹配到最后一个)的任何0+字符(如果未启用DOTALL修饰符,则不匹配换行符),并且不考虑正确嵌套的括号。

要使用Python中的正则表达式正确删除嵌套括号,可以在中使用简单的^{}(匹配a(,然后使用0+字符而不是(),然后使用a)),而使用^{}块:

def remove_text_between_parens(text):
    n = 1  # run at least once
    while n:
        text, n = re.subn(r'\([^()]*\)', '', text)  # remove non-nested/flat balanced parts
    return text

基本上:去掉里面没有()(...),直到没有匹配。用法:

print(remove_text_between_parens('stuff (inside (nested) brackets) (and (some(are)) here) here'))
# => stuff   here

也可以使用非regex方式:

def removeNestedParentheses(s):
    ret = ''
    skip = 0
    for i in s:
        if i == '(':
            skip += 1
        elif i == ')'and skip > 0:
            skip -= 1
        elif skip == 0:
            ret += i
    return ret

x = removeNestedParentheses('stuff (inside (nested) brackets) (and (some(are)) here) here')
print(x)              
# => 'stuff   here'

another Python demo

相关问题 更多 >