【问题标题】:Split a string with custom delimiter, respect and preserve quotes (single or double)使用自定义分隔符拆分字符串,尊重并保留引号(单引号或双引号)
【发布时间】:2019-11-09 12:23:15
【问题描述】:

我有一个这样的字符串:

>>> s = '1,",2, ",,4,,,\',7, \',8,,10,'
>>> s
'1,",2, ",,4,,,\',7, \',8,,10,'

我想使用不同的分隔符 (not just white spaces) 将其拆分,并且我还想尊重和保留引号(单引号或双引号)。

在分隔符 , 上拆分 s 时的预期结果:

['1', ',2, ', '', '4', '', '', ',7, ', '8', '', '10', '']

【问题讨论】:

    标签: python regex


    【解决方案1】:

    this 的修改版本(仅处理空格)可以解决问题(引号被删除):

    >>> import re
    >>> s = '1,",2, ",,4,,,\',7, \',8,,10,'
    
    >>> tokens = [t for t in re.split(r",?\"(.*?)\",?|,?'(.*?)',?|,", s) if t is not None ]
    >>> tokens
    ['1', ',2, ', '', '4', '', '', ',7, ', '8', '', '10', '']
    

    如果你喜欢保留引号字符:

    >>> tokens = [t for t in re.split(r",?(\".*?\"),?|,?('.*?'),?|,", s) if t is not None ]
    >>> tokens
    ['1', '",2, "', '', '4', '', '', "',7, '", '8', '', '10', '']
    

    如果您想使用自定义分隔符,请将正则表达式中出现的, 替换为您自己的分隔符。

    解释:

    | = match alternatives e.g. ( |X) = space or X
    .* = anything
    x? = x or nothing
    () = capture the content of a matched pattern
    
    We have 3 alternatives:
    
    1 "text"    -> ".*?" -> due to escaping rules becomes - > \".*?\"
    2 'text'    -> '.*?'
    3 delimiter ->  ,
    
    Since we want to capture the content of the text inside the quotes, we use ():
    
    1 \"(.*?)\"   (to keep the quotes use (\".*?\")
    2 '(.*?)'     (to keep the quotes use ('.*?')
    
    Finally we don't want that split function reports an empty match if a
    delimiter precedes and follows quotes, so we capture that possible
    delimiter too:
    
    1 ,?\"(.*?)\",?
    2 ,?'(.*?)',?
    
    Once we use the | operator to join the 3 possibilities we get this regexp:
    
    r",?\"(.*?)\",?|,?'(.*?)',?|,"
    

    【讨论】:

      【解决方案2】:

      看起来您正在重新发明 python 模块 csv。包括电池。

      In [1]: import csv
      In [2]: s = '1,",2, ",,4,,,\',7, \',8,,10,'
      In [3]: next(csv.reader([s]))
      Out[3]: ['1', ',2, ', '', '4', '', '', "'", '7', " '", '8', '', '10', '']
      

      我认为,正则表达式通常不是好的解决方案。在意想不到的时刻,它可能会出奇地慢。在csv模块中可以调整方言,很容易处理任意数量的字符串/文件。

      我未能同时将 csv 调整为 quotechar 的两个变体,但您真的需要它吗?

      In [4]: next(csv.reader([s], quotechar="'"))
      Out[4]: ['1', '"', '2', ' "', '', '4', '', '', ',7, ', '8', '', '10', '']
      

      或

      In [5]: s = '1,",2, ",,4,,,",7, ",8,,10,'
      In [6]: next(csv.reader([s]))
      Out[6]: ['1', ',2, ', '', '4', '', '', ',7, ', '8', '', '10', '']
      

      【讨论】:

      • 这是一个有趣的解决方案,谢谢。我没有选择它作为最佳答案,因为它没有完全回答这个问题:单引号或双引号。我也喜欢正则表达式解决方案,因为它可以轻松定制。还是很不错的解决方案
      猜你喜欢
      • 2013-05-18
      • 2012-09-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-02-19
      • 1970-01-01
      • 2017-01-05
      • 2011-04-16
      相关资源
      最近更新 更多