【问题标题】:Split a Python string with nested separated symbol使用嵌套的分隔符号拆分 Python 字符串
【发布时间】:2015-04-22 20:00:23
【问题描述】:

我需要来自字符串

i = "1,'Test','items (one, two, etc.)',1,'long, list'"

提取下一个字符串数组:

['1', "'Test'", "'items (one, two, etc.)'", '1', "'long, list'"]

在正则表达式的帮助下

r=re.split(r',+(?=[^()]*(?:\(|$))', i)

我只收到下一个结果:

['1', "'Test'", "'items (one, two, etc.)'", '1', "'long", " list'"]

UPD1

NULL应该支持

i = "1,'Test',NULL,'items (one, two, etc.)',1,'long, list'"
['1', "'Test'", 'NULL', "'items (one, two, etc.)'", '1', "'long, list'"]

【问题讨论】:

  • 为什么i.split(',') 不能作为解决方案?
  • @letsc 它还会将one, two, etc.'long, list' 用引号括起来。
  • 虽然这不是您所要求的,但您实际上可能想要csv 模块而不是正则表达式(另请参阅this 问题)。
  • @alcedine 我直到现在才阅读您的评论。我的解决方案与您建议的解决方案相同,但我没有从中复制:-)
  • NULL 是怎么回事?它只是 Python 中的另一个字符串

标签: python regex string


【解决方案1】:

在这种情况下,您不需要re.split。您可以在列表理解中使用re.findall

>>> [k for j in re.findall(r"(\d)|'([^']*)'",i) for k in j if k]
['1', 'Test', 'items (one, two, etc.)', '1', 'long, list']

前面的正则表达式将匹配一个引号 '([^']*)' 或任何数字 (\d) 之间的任何内容。

或者在这种情况下,您可以使用ast.literal_eval 作为一种更有效的方式:

>>> from ast import literal_eval
>>> literal_eval(i)
(1, 'Test', 'items (one, two, etc.)', 1, 'long, list')

【讨论】:

  • 在 "i = "1,'Test',NULL,'items (one, two, etc.)',1,'long, list'"" 行中忽略 NULL。如何更新建议的代码也支持 NULL?
  • @constructor 如果您的问题只是NULL 使用>>> [k for j in re.findall(r"(\d)|'([^']*)'|(NULL)",i) for k in j if k]
  • @tommy.carstensen 我解析 SQL 文件并遇到问题。我确信我不是第一个。在我的代码中发现并实现的部分问题的解决方案。我无法解决(正则表达式)已发布的示例。
【解决方案2】:

这是csv 模块的任务:

import csv
from StringIO import StringIO
line = "1,'Test','items (one, two, etc.)',1,'long, list'"
reader = csv.reader(StringIO(line), quotechar="'")
row = next(reader)

# row == ['1', 'Test', 'items (one, two, etc.)', '1', 'long, list']

这里的关键是创建一个CSV阅读器,指定单引号作为引号字符。

【讨论】:

    【解决方案3】:

    你可以用单引号分割:

    i = "1,'Test','items (one, two, etc.)',1,'long, list'"
    
    
    
    print([ele.strip(" ,") for ele in i.split("'") if ele.strip(",")])
    ['1', 'Test', 'items (one, two, etc.)', '1', 'long, list']
    

    或与地图一起使用:

    print([ele for ele in map(lambda x:  x.strip(", "), i.split("'")) if ele])
    

    在 python 3 中使用 map 非常有效:

    In [7]: i = "1,'Test','items (one, two, etc.)',1,'long, list'"
    
    In [8]: timeit [ele for ele in map(lambda x:  x.strip(", "), i.split("'")) if ele]
    1000000 loops, best of 3: 1.5 µs per loop
    
    In [9]: r = re.compile(r"(\d)|'([^']*)'") 
    
    In [10]: timeit [k for j in r.findall(i) for k in j if k]
    100000 loops, best of 3: 3.92 µs per loop
    

    最好使用python2和itertools.imap

    In [9]: from itertools  import imap   
    In [10]: timeit [ele for ele in imap(lambda x:  x.strip(", "), i.split("'")) if ele]
    1000000 loops, best of 3: 871 ns per loop  
    
    In [11]: r = re.compile(r"(\d)|'([^']*)'")
    In [12]: timeit [k for j in r.findall(i) for k in j if k]
    100000 loops, best of 3: 4.27 µs per loop
    
    In [17]: from ast import literal_eval
    In [18]: timeit literal_eval(i)
    100000 loops, best of 3: 16.2 µs per loop
    

    所有这些都返回相同的输出栏literal_eval,因为它将数字评估为整数:

    In [19]: literal_eval(i)
    Out[19]: (1, 'Test', 'items (one, two, etc.)', 1, 'long, list')
    
    In [20]: [k for j in r.findall(i) for k in j if k]
    Out[20]: ['1', 'Test', 'items (one, two, etc.)', '1', 'long, list']
    
    In [21]: [ele for ele in imap(lambda x:  x.strip(", "), i.split("'")) if ele]Out[21]: ['1', 'Test', 'items (one, two, etc.)', '1', 'long, list']
    

    NUll 行没有什么不同:

    i = "1,'Test',NULL,'items (one, two, etc.)',1,'long, list'"
    
    
    
    print([ele for ele in map(lambda x:  x.strip(", "), i.split("'")) if ele])
    
    ['1', 'Test', 'NULL', 'items (one, two, etc.)', '1', 'long, list']
    

    【讨论】:

      猜你喜欢
      • 2014-02-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-07-05
      • 1970-01-01
      • 1970-01-01
      • 2018-12-21
      相关资源
      最近更新 更多