正则表达式按括号分割,但不是所有的括号。

3
我正在尝试拆分一个包含开放和关闭括号的字符串,但希望排除那些在它们之前有子字符串的括号。 在以下示例中:
a = 'abc (xyz pqr) qwe ew (kjlk asd) ue(aad) kljl'

我想要一个像这样的列表:
['abc', 'xyz pqr', 'qwe ew', 'kjlk asd', 'ue(aad)', 'kljl']

所以我想保留ue(aad),不要按(aad)拆分

我已经尝试过:

y = [x.strip() for x in re.split(r"[^ue()][()]", a) if x.strip()]
4个回答

2

试试这个:

import re

a = 'abc (xyz pqr) qwe ew (kjlk asd) ue(aad) kljl'
y = [x.strip() for x in re.split(r' (\S*\(.*?\))', a) if x != '']
for i in range(len(y)):
    if y[i][0] == '(' and y[i][-1] == ')':
        y[i] = y[i].strip('()')

print(y)  # => ['abc', 'xyz pqr', 'qwe ew', 'kjlk asd', 'ue(aad)', 'kljl']

正则表达式 (\S*\(.*?\)) 将匹配任何括号及其前面的字符串,然后循环将没有前导字符串的匹配项中的周围括号删除。

a = "a b(c)d" 会产生 ['a', 'b(c)', 'd'] - 我怀疑这不是预期的行为。 - Dillon Davis
这个无法分割嵌套的括号,但是给了我一个想法,在括号前面添加一个空格来忽略像ue(aad)这样的情况。 - Will Jue
@DillonDavis 这个问题只要求处理括号前的字符串。但是,如果需要处理这种情况,那么你只需要在正则表达式的末尾添加另一个\S*,就像这样 (\S*\(.*?\)\S*) - Michael M.

0

由于在我的情况下关键字总是已知的,我考虑删除所有的ue(.*?)s并将它们保存在列表中,然后按括号分割再进行替换。 这样我就能够分割嵌套的括号。 类似这样:

a = "abc (xyz pqr) qwe ew (kjlk asd) ue(aad) kljl"
ues = re.findall("ue\(.*?\)", a)
j = re.sub("(?<=ue)\(.*?\)", "", a)
y = [x.strip() for x in re.split(r"[()]", j) if x.strip()]
for i in y:
    if "ue" in i:
        print(re.sub("ue", ues.pop(0), i))
    else: 
        print(i)

更新: 必须忽略的括号将有一个类似于ue()的子字符串附着在其上,因此在其前面添加一个空格将忽略它们。

y = [x.strip() for x in re.split(r"[(?<=\s)][()]", a) if x.strip()]  

这只能解决例子,而不能解决通用情况。 - handras

0

对于你的示例数据,你可以使用捕获组来保留拆分后的结果。在模式中,捕获括号前后的非空白字符,但不包括括号本身。

在列表推导中,首先检查 x,然后再测试 x.strip()

请注意,这不考虑任何嵌套/平衡的括号。

解释

  • ([^\s()]+\([^()]*\)) 捕获组1,匹配从(...)之前的1个或多个非空白字符
  • | 或者
  • (\([^()]*\)[^\s()]+) 捕获组2,匹配从(...)之后的1个或多个非空白字符
  • | 或者
  • [()] 匹配()

请查看Python演示regex101演示

import re

pattern = r"([^\s()]+\([^()]*\))|(\([^()]*\)[^\s()]+)|[()]"
a = 'abc (xyz pqr) qwe ew (kjlk asd) ue(aad) kljl'

y = [x.strip() for x in re.split(pattern, a) if x and x.strip()]
print(y)

输出

['abc', 'xyz pqr', 'qwe ew', 'kjlk asd', 'ue(aad)', 'kljl']

-1

这是一种奇怪的方法来完成这个任务,但它确实有效:

import re

a = "abc (xyz pqr) qwe ew (kjlk asd) ue(aad) kljl"

dissub=re.split("\)\s",a)
newlist=[]
for b in dissub:
    dasplit=re.split("\s\(",b)
    for c in dasplit:

        newlist.append(c)
i=0
while i<len(newlist):
    dacheck=re.search("\(",newlist[i])
    if dacheck:
        newlist[i]+=")"
    i+=1
print(newlist)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接