在python中分割逗号分隔的字符串


问题内容

这个问题已经被问过很多次了。一些例子:[1][2]。但是似乎没有更一般的东西。我正在寻找的是一种在引号或定界符对之内的逗号分隔字符串的方法。例如:

s1 = 'obj<1, 2, 3>, x(4, 5), "msg, with comma"'

应该分为三个元素的列表

['obj<1, 2, 3>', 'x(4, 5)', '"msg, with comma"']

现在的问题是,由于我们可以查看成对的<>和,因此这可能变得更加复杂()

s2 = 'obj<1, sub<6, 7>, 3>, x(4, y(8, 9), 5), "msg, with comma"'

应该分为:

['obj<1, sub<6, 7>, 3>', 'x(4, y(8, 9), 5)', '"msg, with comma"']

不使用正则表达式的简单方法是通过查找字符来解析字符串,<(。如果找到<(,则我们开始计算奇偶校验。如果奇偶校验为零,我们只能以逗号分隔。举例说,我们要分开s2,我们可以开始`parity

0,当我们到达s2[3]我们遇到<这将增加平价1。当遇到奇偶只会减少>或者)当它遇到它会增加<(`。当奇偶校验不为0时,我们可以简单地忽略逗号而不进行任何拆分。

这里的问题是,使用正则表达式可以快速解决此问题吗?我确实在研究此解决方案,但似乎并不涵盖我所给出的示例。

一个更通用的函数将是这样的:

def split_at(text, delimiter, exceptions):
    """Split text at the specified delimiter if the delimiter is not
    within the exceptions"""

一些用途是这样的:

split_at('obj<1, 2, 3>, x(4, 5), "msg, with comma"', ',', [('<', '>'), ('(', ')'), ('"', '"')]

正则表达式将能够处理此问题,还是有必要创建专门的解析器?


问题答案:

虽然不可能使用正则表达式,但是以下简单代码将实现所需的结果:

def split_at(text, delimiter, opens='<([', closes='>)]', quotes='"\''):
    result = []
    buff = ""
    level = 0
    is_quoted = False

    for char in text:
        if char in delimiter and level == 0 and not is_quoted:
            result.append(buff)
            buff = ""
        else:
            buff += char

            if char in opens:
                level += 1
            if char in closes:
                level -= 1
            if char in quotes:
                is_quoted = not is_quoted

    if not buff == "":
        result.append(buff)

    return result

在解释器中运行此命令:

>>> split_at('obj<1, 2, 3>, x(4, 5), "msg, with comma"', ',')                                                                                                                                 
#=>['obj<1, 2, 3>', ' x(4, 5)', ' "msg with comma"']