我需要在分号上分割这样的字符串.但我不想拆分字符串('或')内的分号.我没有解析文件;只是一个没有换行符的简单字符串.
part 1;"this is ; part 2;";'this is ; part 3';part 4;this "is ; part" 5
结果应该是:
我想这可以用正则表达式完成,但如果没有; 我对另一种方法持开放态度.
Dun*_*can 50
大多数答案似乎都过于复杂.你并不需要反向引用.你并不需要依赖于是否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]
Run Code Online (Sandbox Code Playgroud)
输出是:
['part 1', '"this is ; part 2;"', "'this is ; part 3'", 'part 4', 'this "is ; part" 5']
Run Code Online (Sandbox Code Playgroud)
正如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'"]
Run Code Online (Sandbox Code Playgroud)
然而,这是一个kludge.有更好的建议吗?
Ala*_*ore 32
re.split(''';(?=(?:[^'"]|'[^']*'|"[^"]*")*$)''', data)
Run Code Online (Sandbox Code Playgroud)
每次找到分号时,前瞻扫描整个剩余的字符串,确保有偶数个单引号和偶数个双引号.(双引号字段内的单引号,反之亦然,将被忽略.)如果前瞻成功,则分号是分隔符.
与Duncan的解决方案不同,Duncan的解决方案与字段匹配而不是分隔符,这个字段与空字段没有问题.(甚至不是最后一个:与许多其他split实现不同,Python不会自动丢弃尾随的空字段.)
小智 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']
Run Code Online (Sandbox Code Playgroud)
Pau*_*McG 11
这是一个带注释的pyparsing方法:
from pyparsing import (printables, originalTextFor, OneOrMore,
quotedString, Word, delimitedList)
# unquoted words can contain anything but a semicolon
printables_less_semicolon = printables.replace(';','')
# capture content between ';'s, and preserve original text
content = originalTextFor(
OneOrMore(quotedString | Word(printables_less_semicolon)))
# process the string
print delimitedList(content, ';').parseString(test)
Run Code Online (Sandbox Code Playgroud)
给
['part 1', '"this is ; part 2;"', "'this is ; part 3'", 'part 4',
'this "is ; part" 5']
Run Code Online (Sandbox Code Playgroud)
通过使用提供的pyparsing quotedString,您还可以获得对转义引号的支持.
您还不清楚如何在分号分隔符之前或之后处理前导空格,并且示例文本中的所有字段都没有.Pyparsing会将"a; b; c"解析为:
['a', 'b', 'c']
Run Code Online (Sandbox Code Playgroud)
您似乎有一个分号分隔的字符串.为什么不使用该csv模块来完成所有的艰苦工作?
在我的头顶,这应该工作
import csv
from StringIO import StringIO
line = '''part 1;"this is ; part 2;";'this is ; part 3';part 4;this "is ; part" 5'''
data = StringIO(line)
reader = csv.reader(data, delimiter=';')
for row in reader:
print row
Run Code Online (Sandbox Code Playgroud)
这应该给你一些类似的东西
("part 1", "this is ; part 2;", 'this is ; part 3', "part 4", "this \"is ; part\" 5")
编辑:
不幸的是,由于混合字符串引号(单引号和双引号),这不起作用(即使你按照我的意图使用StringIO).你真正得到的是
['part 1', 'this is ; part 2;', "'this is ", " part 3'", 'part 4', 'this "is ', ' part" 5'].
如果您可以将数据更改为仅在适当的位置包含单引号或双引号,它应该可以正常工作,但这种方式可以消除这个问题.