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

Cle*_*leb 6 python regex parentheses

当我有这样的字符串:

s1 = 'stuff(remove_me)'
Run Code Online (Sandbox Code Playgroud)

我可以轻松删除括号和使用中的文本

# returns 'stuff'
res1 = re.sub(r'\([^)]*\)', '', s1)
Run Code Online (Sandbox Code Playgroud)

为解释在这里.

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

s2 = 'stuff(remove(me))'
Run Code Online (Sandbox Code Playgroud)

当我从上面运行命令时,我最终得到了

'stuff)'
Run Code Online (Sandbox Code Playgroud)

我也尝试过:

re.sub('\(.*?\)', '', s2)
Run Code Online (Sandbox Code Playgroud)

这给了我相同的输出.

如何删除外括号内的所有内容 - 包括括号本身 - 以便我最终得到'stuff'(这应该适用于任意复杂的表达式)?

Wik*_*żew 10

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

与Python中的正则表达式正确删除嵌套的括号,则可以使用一个简单的\([^()]*\)(匹配(,然后0+比其它字符(),然后)在a)中,而使用块re.subn:

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
Run Code Online (Sandbox Code Playgroud)

基本上:删除(...)no ()inside,直到找不到匹配项.用法:

print(remove_text_between_parens('stuff (inside (nested) brackets) (and (some(are)) here) here'))
# => stuff   here
Run Code Online (Sandbox Code Playgroud)

非正则表达方式也是可能的:

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'
Run Code Online (Sandbox Code Playgroud)

另一个Python演示


bob*_*ble 5

如前所述,您需要一个递归正则表达式来匹配任意级别的嵌套,但是如果您知道最多只能嵌套一个级别,请尝试以下模式:

\((?:[^)(]|\([^)(]*\))*\)
Run Code Online (Sandbox Code Playgroud)
  • [^)(]匹配不是括号的字符(否定的类)。
  • |\([^)(]*\)或与另一( )对内含任何数量的 内含物)(
  • (?:... )*所有这些时间都在里面( )

这是regex101的演示

[^)(]不带+量词的替换之前,如果不平衡,则失败更快。
您需要添加可能发生的更多级别的嵌套。例如,最多2个级别:

\((?:[^)(]|\((?:[^)(]|\([^)(]*\))*\))*\)
Run Code Online (Sandbox Code Playgroud)

regex101上的另一个演示


ale*_*ici 1

re匹配是渴望的,因此它们尝试匹配尽可能多的文本,对于您提到的简单测试用例,只需让正则表达式运行:

>>> re.sub(r'\(.*\)', '', 'stuff(remove(me))')
'stuff'
Run Code Online (Sandbox Code Playgroud)

  • @Cleb 请注意,这不会检查大括号是否匹配。例如,在 `foo(bar)baz(spam)e)ggs` 中,它只会留下 `fooggs`。 (6认同)