如何在Python中拆分但忽略引号中的分隔符?
我需要把一个字符串按照分号来分割。但是,我不想分割那些在字符串内部的分号(比如在单引号或双引号里面的)。我不是在解析文件,只是处理一个简单的字符串,没有换行。
part 1;"this is ; part 2;";'this is ; part 3';part 4;this "is ; part" 5
结果应该是:
- part 1
- "this is ; part 2;"
- 'this is ; part 3'
- part 4
- this "is ; part" 5
我想这可以用正则表达式来实现,但如果不行,我也愿意尝试其他方法。
17 个回答
这段代码是用来做某些操作的,但具体的功能需要根据上下文来理解。一般来说,代码块里面的内容会包含一些指令或者逻辑,用来处理数据或者实现特定的功能。
如果你看到这样的代码块,通常意味着这里有一些重要的代码需要关注。理解这些代码的作用,可以帮助你更好地掌握编程的基本概念。
记住,编程就像是给计算机下指令,代码块就是这些指令的集合。每一行代码都有它的意义,理解它们的作用是学习编程的关键。
>>> a='A,"B,C",D'
>>> a.split(',')
['A', '"B', 'C"', 'D']
It failed. Now try csv module
>>> import csv
>>> from StringIO import StringIO
>>> data = StringIO(a)
>>> data
<StringIO.StringIO instance at 0x107eaa368>
>>> reader = csv.reader(data, delimiter=',')
>>> for row in reader: print row
...
['A,"B,C",D']
re.split(''';(?=(?:[^'"]|'[^']*'|"[^"]*")*$)''', data)
每当它找到一个分号时,预查看会扫描剩下的整个字符串,确保单引号和双引号的数量都是偶数。(在双引号字段内的单引号,或者在单引号字段内的双引号,会被忽略。)如果预查看成功,那么这个分号就可以作为分隔符。
与Duncan的解决方案不同,后者是匹配字段而不是分隔符,这个方法对空字段没有问题。(甚至最后一个字段也不会出问题:与许多其他split
实现不同,Python的实现不会自动丢弃末尾的空字段。)
大部分的回答看起来都复杂得多。其实你不需要用到回溯引用,也不需要依赖于re.findall是否能找到重叠的匹配项。因为输入数据不能用csv模块来解析,所以用正则表达式几乎是唯一的选择。你只需要用re.split来调用一个匹配字段的模式就可以了。
注意,这里匹配字段比匹配分隔符要简单得多:
import re
data = """part 1;"this is ; part 2;";'this is ; part 3';part 4;this "is ; part" 5"""
PATTERN = re.compile(r'''((?:[^;"']|"[^"]*"|'[^']*')+)''')
print PATTERN.split(data)[1::2]
输出结果是:
['part 1', '"this is ; part 2;"', "'this is ; part 3'", 'part 4', 'this "is ; part" 5']
正如Jean-Luc Nacif Coelho正确指出的,这种方法对空组的处理不太准确。根据具体情况,这可能会有影响,也可能没有。如果有影响,可以尝试通过将';;'
替换为';<marker>;'
来处理,其中<marker>
应该是一个你知道在数据中不会出现的字符串(不能包含分号)。另外,处理完后你还需要恢复数据:
>>> marker = ";!$%^&;"
>>> [r.replace(marker[1:-1],'') for r in PATTERN.split("aaa;;aaa;'b;;b'".replace(';;', marker))[1::2]]
['aaa', '', 'aaa', "'b;;b'"]
不过这只是个权宜之计。有没有更好的建议呢?