【问题标题】:Python: Split string by patternPython:按模式拆分字符串
【发布时间】:2014-01-29 06:40:29
【问题描述】:

我的问题是 this one 的变体。我好像搞不懂这个。

given = "{abc, xyz}, 123, {def, lmn, ijk}, {uvw}, opq"
expected = ["{abc, xyz}", "123", "{def, lmn, ijk}", "{uvw}", "opq"]

如上例所示,expected 中的项目可能是 {..., ...} 或只是另一个 string

非常感谢。

【问题讨论】:

  • 如果花括号可以嵌套,则不能使用正则表达式拆分它(至少不能以“纯”形式),因为它不是上下文无关语法。

标签: python regex string split


【解决方案1】:

我认为以下正则表达式适合这项工作。但是您不必嵌套大括号(据我所知,无法使用正则表达式解析嵌套大括号)

>>> s= "{abc, xyz}, 123, {def, lmn, ijk}, {uvw}, opq"
>>> re.findall(r",?\s*(\{.*?\}|[^,]+)",s)
['{abc, xyz}', '123', '{def, lmn, ijk}', '{uvw}', 'opq']

【讨论】:

  • 可能值得注意的是为什么嵌套的大括号可能无法使用正则表达式解决...
  • 正如@shx2 上面提到的,带有嵌套大括号的语言是上下文无关的,需要下推自动机来解决。 Python 中的正则表达式或多或少是正则语言的实现,由有限自动机解析,因此功能较弱。
  • @Xavier_Combelle 谢谢!
  • 我会将:\{.*?\} 更改为 \{[^}]*\}。它避免了非贪婪匹配(可能会更慢)并且即使字符串包含换行符也会匹配。您当前的解决方案无法匹配 {abc,\nxyz} 之类的内容。
【解决方案2】:
given = "{abc,{a:b}, xyz} , 123 , {def, lmn, ijk}, {uvw}, opq"
#expected = ["{abc, xyz}", "123", "{def, lmn, ijk}", "{uvw}", "opq"]
tmp_l = given.split(',')
tmp_l = [i.strip() for i in tmp_l]
result_l = []
element = ''
count = 0
for i in tmp_l:
    if i[0] == '{':
        count += 1
    if i[-1] == '}':
        count -= 1
    element = element + i + ','
    if count == 0:
        element = element[0:-1]
        result_l.append(element)
        element = ''

print str(result_l)

这个可以处理嵌套的大括号,虽然看起来不那么优雅..

【讨论】:

    【解决方案3】:

    以下内容没有为您提供您正在寻找的东西吗?

    import re
    given = "{abc, xyz}, 123, {def, lmn, ijk}, {uvw}, opq"
    expected = re.findall(r'(\w+)', given)
    

    我在终端中运行它并得到:

    >>> import re
    >>> given = "{abc, xyz}, 123, {def, lmn, ijk}, {uvw}, opq"
    >>> expected = re.findall(r'(\w+)', given)
    >>> expected
    ['abc', 'xyz', '123', 'def', 'lmn', 'ijk', 'uvw', 'opq']
    

    【讨论】:

    • 不是这样,例如,'abc' 和 'xyz' 不应该是单独的词,如果它们在同一组括号中。
    【解决方案4】:

    您可以使用下面的正则表达式来做到这一点。其余与您提供的类似链接相同。

    given = "{abc, xyz}, 123, {def, lmn, ijk}, {uvw}, opq"
    regex = r",?\s*(\{.*?\}|[^,]+)"
    
    print re.findall(regex,given)
    
    OP: ['{abc, xyz}', '123', '{def, lmn, ijk}', '{uvw}', 'opq']
    

    只需导入re 模块。并按照链接中的说明进行操作。 它将匹配花括号 { } 和任何字符串内的任何内容。

    【讨论】:

    • 你需要在某个地方 re.findall 你所拥有的只是一个元组
    • 他已经给出了解释其余部分的链接。不是吗