逗号中的拆分字符串在python中的圆括号或大括号中不存在

时间:2018-08-17 00:19:04

标签: python regex python-2.7 list

下面是我要用逗号分割的字符串。

如果()或{}中包含逗号,则不应拆分该字符串。

我正在使用以下代码进行拆分:

目前仅处理(),我如何也包含{}?

import re
s = "Water,^.*f04.*&~(.*z.,*)$,Iron Oxides (CI 77491, 77492),a{3,4}"
print re.split(r',\s*(?![^()]*\))', s)

输出应为:

[Water,^.*f04.*&~(.*z.,*)$,Iron Oxides (CI 77491, 77492),a{3,4}]

2 个答案:

答案 0 :(得分:1)

假设方括号可以嵌套,那么您所用的不是普通语言。尽管re确实有很多扩展名可以处理实际的正则表达式以外的内容,但最好还是用一个简单的方括号计数解析器来解决这个问题。

类似这样的东西(未经测试,但应该足够简单以了解和调试):

bracketmap = {'(': ')', '[': ']', '{': '}'}

def splitify(s):
    stack = []
    lastcomma = 0
    for i, c in enumerate(s):
        if not stack and c == ',':
            yield s[lastcomma:i]
            lastcomma = i+1
        elif c in bracketmap:
            stack.append(bracketmap[c])
        elif c in ')]}':
            if stack.pop() != c:
                raise ValueError('unbalanced brackets')
    if stack:
        raise ValueError('unbalanced brackets')
    if lastcomma <= len(s):
        yield s[lastcomma:]

在评论中,当被问到方括号是否可以嵌套时,您说:

  

如果它似乎是有效的正则表达式就可以。

因此,如果该字符串实际上是要作为正则表达式模式的,则您需要做的不只是排除括号内的逗号。例如,\{,\}不是大括号内的逗号,而是完全正常的文字逗号。

编写一个完整的regex解析器显然比仅计算括号对要复杂一些(尽管如果您确实需要Python re语法,则可以使用该库进行编译,然后使用该库的调试工具扫描文字原边,而不是自己编写……),但是也许您可以只计算未转义的括号对就可以逃脱?

    esc = False
    for i, c in enumerate(s):
        if esc:
            esc = False
        elif c = '\\':
            esc = True
        elif not stack and c == ',':
            # same as before

(我在这里假设您不想将\,当作字面逗号。如果您这样做,那是微不足道的更改。)

答案 1 :(得分:1)

借助regex模块,该模块允许在后面进行变长查找:

regex.split(r'(?<![({][^,]*),(?![^,]*[})])', str_)
  • (?<![({][^,]*)是一个零宽度的负向后方,确保,之前没有({并且没有,在两者之间

  • ,匹配文字,

  • (?![^,]*[})])是零宽度的负向超前行,可确保,后没有任何中间,后跟)或{{1} }

示例:

}

限制:

  • In [1287]: str_ = "Water,^.*f04.*&~(.*z.,*)$,Iron Oxides (CI 77491, 77492),a{3,4}" In [1288]: regex.split(r'(?<![({][^,]*),(?![^,]*[})])', str_) Out[1288]: ['Water', '^.*f04.*&~(.*z.,*)$', 'Iron Oxides (CI 77491, 77492)', 'a{3,4}'] 匹配[({] / (中的任何一个,而{匹配[})] / )中的任何一个,因此可以导致错误,例如子字符串以}开头,以(结束,或者以其他方式结束

  • 不适用于嵌套的括号/括号