假设您从 CSV 中读取一行:
from StringIO import StringIO
import csv
infile = StringIO('hello,"foo, bar"')
reader = csv.reader(infile)
row = reader.next() # row is ['hello', 'foo, bar']
该行中的第二个值是foo, bar
代替"foo, bar"
。这不是什么 Python 怪事,而是对 CSV 语法的合理解释。引号可能不是作为值的一部分放在那里,而是为了表明这一点foo, bar
是一个值,不应拆分为foo
and bar
基于逗号 (,
)。另一种解决方案是在创建 CSV 文件时转义逗号,因此该行将如下所示:
hello,foo \,bar
所以想要保留这些引用是一个很奇怪的请求。如果我们更多地了解您的用例和更大的前景,我们可以更好地帮助您。你想达到什么目的?输入文件从哪里来?它真的是 CSV 还是其他看起来类似的语法?例如,如果您知道每一行都包含两个用逗号分隔的值,并且第一个值从不包含逗号,那么您可以在第一个逗号上进行拆分:
print 'hello,"foo, bar"'.split(',', 1) # => ['hello', '"foo, bar"']
但我怀疑输入是否有这样的限制,这就是为什么需要像引号这样的东西来解决歧义。
如果您尝试再次写入 CSV,则系统会在您执行此操作时重新创建引号。它们不必出现在中间列表中:
outfile = StringIO()
writer = csv.writer(outfile)
writer.writerow(row)
print outfile.getvalue()
这将打印
hello,"foo, bar"
您可以通过设置新的方言来自定义精确的 CSV 输出。
如果您想获取行中的各个值并对其应用适当的引用规则,这是可能的,但这有点麻烦:
# We're going to write individual strings, so we don't want a line terminator
csv.register_dialect('no_line_terminator', lineterminator='')
def maybe_quote_string(s):
out = StringIO()
# writerow iterates over its argument, so don't give it a plain string
# or it'll break it up into characters
csv.writer(out, 'no_line_terminator').writerow([s])
return out.getvalue()
print maybe_quote_string('foo, bar')
print map(maybe_quote_string, row)
输出是:
"foo, bar"
['hello', '"foo, bar"']
这是我能最接近回答你的问题。这不是真的keeping双引号,而是删除它们并使用可能与最初将它们放在那里的相同规则将它们添加回来。
我再说一遍,你可能在这个问题上走错了路。其他人可能会同意。这就是为什么你很难得到好的答案。您想要解决的更大问题是什么?我们可以帮助您更好地实现这一目标。