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

问题描述 投票:0回答:7

当我有这样的字符串时:

s1 = 'stuff(remove_me)'

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

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

此处所解释。

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

s2 = 'stuff(remove(me))'

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

'stuff)'

我也尝试过:

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

这给了我相同的输出。

如何删除外括号内的所有内容 - 包括括号本身 - 以便我最终也得到

'stuff'
(这应该适用于任意复杂的表达式)?

python regex parentheses
7个回答
19
投票

注意

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

要在Python中使用正则表达式正确删除嵌套括号,您可以使用简单的

\([^()]*\)
(匹配
(
,然后匹配除
(
)
之外的0+个字符,然后匹配
)
)在 while 块中使用
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

基本上:删除里面没有

(...)
(
)
,直到找不到匹配项。用途:

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

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

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'

参见 另一个 Python 演示


6
投票

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

\((?:[^)(]|\([^)(]*\))*\)
  • [^)(]
    匹配一个字符,该字符不是括号(否定类)。
  • |\([^)(]*\)
    或与另一个
    (
    )
    配对,其中包含任意数量的 non
    )(
  • (?:
    ...
    )*
    所有这些都可以在
    (
    )
  • 内任意次数

这是 regex101 的演示

在交替使用

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

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

regex101 的另一个演示


1
投票

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

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

1
投票

如果你确定括号最初是平衡的,只需使用greedy版本:

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

1
投票

https://regex101.com/r/kQ2jS3/1

'(\(.*\))'

这捕获了

furthest
括号以及括号之间的所有内容。

您的旧正则表达式捕获第一个括号,以及

next
括号之间的所有内容。


0
投票

我在这里找到了解决方案:

http://rachbelaid.com/recursive-regular-experession/

上面写着:

>>> import regex
>>> regex.search(r"^(\((?1)*\))(?1)*$", "()()") is not None
True
>>> regex.search(r"^(\((?1)*\))(?1)*$", "(((()))())") is not None
True
>>> regex.search(r"^(\((?1)*\))(?1)*$", "()(") is not None
False
>>> regex.search(r"^(\((?1)*\))(?1)*$", "(((())())") is not None
False

0
投票

没有 Python 循环。没有递归。没有正则表达式。

只需减去

'('
')'
的累计计数:

import numpy as np
s = '()a(x(x)x)b(x)c()d()'
s_array = np.array(list(s))
mask_open = s_array=='('
mask_close = s_array==')'
result = ''.join(s_array[(np.cumsum(mask_open) - np.cumsum(mask_close) + mask_close) < 1])

这可能比其他解决方案更快。

© www.soinside.com 2019 - 2024. All rights reserved.