嗨我有一个带字符串的文本文件:
你好," foo,bar"
我想将其拆分为以下列表:
['hello', '"foo, bar"']
有没有办法可以实现这个目标?
我现在正在尝试这个:
for line in sys.stdin:
csv_file = StringIO.StringIO(line)
csv_reader = csv.reader(csv_file)
我希望它们分成两个字符串,即:
'hello' and '"foo, bar"'
答案 0 :(得分:1)
假设您从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
和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"']
这是我最接近回答你问题的方法。它并不是真的保留双引号,而是将它们删除并添加回来,可能与首先放置它们的规则相同。
我会再说一遍,你可能会在这个问题上走错路。其他人可能会同意。这就是为什么你在努力获得好的答案。你想要解决的更大问题是什么?我们可以帮助您更好地实现这一目标。
答案 1 :(得分:0)
好吧所以这需要很长时间才能得到一个解决方案而且它不是很漂亮,但是:
>>> import re
>>> s = 'hello,"foo, bar"'
>>>
>>> replacements = {}
>>> m = re.search("\".*\"", s)
>>> while m:
... key = 'unique_phrase_' + str(len(replacements))
... replacements[key] = s[m.span()[0]:m.span()[1]]
... s = re.sub("\".*\"", key, s, count=1)
... m = re.search("\".*\"", s)
...
>>> list_from_string = s.split(",")
>>> final_list = []
>>> for element in list_from_string:
... for key in replacements.keys():
... if re.match(key, element):
... final_list.append(re.sub(key, replacements[key], element))
... else:
... final_list.append(element)
...
>>>
>>> print final_list
['hello', '"foo, bar"']
对我来说看起来很丑,但是找不到任何明确的方法让它变得更加pythonic。
答案 2 :(得分:0)
派对有点晚,但在CSV库中有quoting可以做你想要的(设置为QUOTE_NONE)