Exotic CSV Dialect Parsing
我似乎找不到正确的python3 csv阅读器参数来解析这个特定的csv方言。生成csv的对象的行为如下:
分析器信息:
- 引号字符:"(x22)
- 字段分隔符:^(x5e)
- 记录分隔符:(x0A)
- 转义符(x5c)
生成此格式的csv如何工作:
- 如果在字段中找到指定的记录分隔符,则引号字段
- 如果在字段中找到指定的字段分隔符,请引用该字段。
- 如果在字段中找到指定的引号字符,请引用该字段并转义引号字符
- 如果在字段中找到指定的转义符,则不执行任何操作…
^最后一点是导致我出现问题的原因,因为特定行的第一个字段以反斜杠结尾。这会导致python3 csv解析器将第一个字段分隔符解释为转义。
见下文:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | (xcve) ttucker@plato:~/tmp/csv$ python --version Python 3.6.4 (xcve) ttucker@plato:~/tmp/csv$ cat test_csv.py import csv with open('exotic_dialect.csv') as f: data = f.readlines() reader = csv.reader(data, delimiter='^', quotechar='"', escapechar='\', quoting=csv.QUOTE_MINIMAL) for row in reader: print(row) (xcve) ttucker@plato:~/tmp/csv$ cat exotic_dialect.csv a^b^c a|^b^c "a""^b^c "a^"^b^c a\^b^c (xcve) ttucker@plato:~/tmp/csv$ python test_csv.py ['a', 'b', 'c'] ['a|', 'b', 'c'] ['a"', 'b', 'c'] ['a^', 'b', 'c'] ['a^b', 'c'] ^ This last list should have three fields; i.e., ['a\', 'b', 'c'] |
所以,我的问题是:
因此,首先对数据进行字符串替换不是最好的主意,因为没有任何方法可以确定是否应该在不了解上下文的情况下对未捕获的转义符进行转义。我最后只写了自己的解析器。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 | class XcCsv(object): def __init__(self, field_delim, record_delim, quote_char, escape_char): self._field_delim = field_delim self._record_delim = record_delim self._quote_char = quote_char self._escape_char = escape_char self._records = [] self._record_buf = [] self._field_buf ="" self._in_quote = False self._in_escape = False # This could be different ... def _walker(self, data): data_length = len(data) if data_length == 1: self._parse_char(data) else: for d in data: self._walker(d) def _parse_char(self, char): if self._in_escape: self._field_buf += char self._in_escape = False elif char == self._escape_char: if self._in_quote: self._in_escape = True else: self._field_buf += char elif char == self._quote_char: if self._in_quote: if self._in_escape == True: self._field_buf += char else: self._in_quote = False else: self._in_quote = True elif char == self._field_delim: if self._in_quote: self._field_buf += char else: self._record_buf.append(self._field_buf) self._field_buf ="" elif char == self._record_delim: if self._in_quote: self._field_buf += char else: self._record_buf.append(self._field_buf) self._records.append(self._record_buf) self._record_buf = [] self._field_buf ="" else: self._field_buf += char def reader(self, data): self._walker(data) for rec in self._records: print(rec) csv = XcCsv("^"," ","'","\") data = open("exotic_dialect.csv").readlines() csv.reader(data) |
我不是这方面的专家,但是
1)可能不会。您希望相同的转义符在此上下文中执行两个不同的操作,这将无法区分。这些csv解析器通常首先处理转义字符。
csv解析器如何确定此示例的正确行为?
fo\^o^bar ["fo\","o","bar"] ["fo^o","bar"]
2)我个人会通过一些预处理来运行您的csv,这样您就可以正确地解析您的文件(用