2013-03-08 3 views
6

Я хочу использовать питон CSV читатель, но я хочу, чтобы оставить кавычки То есть я хочу:.Может ли читатель csv python оставить кавычки?

>>> s = '"simple|split"|test' 
>>> reader = csv.reader([s], delimiter='|', skipinitialspace=True) 
>>> reader.next() 
['"simple|split"', 'test'] 

Но я на самом деле получить:

['simple|split', 'test'] 

В моем случае я хочу цитируемый строка, которая будет передана по еще цитированной.

Я знаю, что читатель CSV работает по назначению, и мой прецедент - это злоупотребление, но есть ли способ согнуть его по моей воле? Или мне нужно написать собственный синтаксический анализатор строк?

+0

Вы будете нужно написать собственный парсер. Кавычки являются средством выхода из данных, которые иначе не могли бы рассматриваться как один столбец и, следовательно, не считались частью вывода. –

+1

В зависимости от того, насколько сложны данные, вы можете обманывать и использовать что-то ужасное, как 'filter (None, re.split (r '(". *? ") | \ |', S))' - или смотреть в 'pyparsing' –

+0

Привет, я отправил ответ, в котором на самом деле я развиваю то, что сказал Марджин и Джон. Не могли бы вы сказать, почему вы не думали использовать регулярное выражение? – eyquem

ответ

3

Вы будете иметь, чтобы написать свой собственный парсер, как часть модуля, примыкающим разбор и котировки в стороне C вещей, в частности, parse_process_char расположенных в Modules/_csv.c:

else if (c == dialect->quotechar && 
      dialect->quoting != QUOTE_NONE) { 
     if (dialect->doublequote) { 
      /* doublequote; " represented by "" */ 
      self->state = QUOTE_IN_QUOTED_FIELD; 
     } 
     else { 
      /* end of quote part of field */ 
      self->state = IN_FIELD; 
     } 
    } 
    else { 
     /* normal character - save in field */ 
     if (parse_add_char(self, c) < 0) 
      return -1; 
    } 

Это Раздел «конец цитаты части поля» - это то, что делает вашу двойную кавычку. С другой стороны, вы можете убить этот else условный и перестроить исходный код python. Однако это не все, что можно скрыть, чтобы быть честным.

Редактировать: К сожалению, я имел в виду добавить немного от последнего else до того self->state = IN_FIELD так он добавляет цитату в

+0

Это довольно окончательный ответ! Спасибо. –

+0

@HamishDowner На самом деле у меня возникла идея по использованию модуля PyPy (Python in Python) и его модификации для создания пользовательской, которая может быть удалена в проект. Я немного поиграю с ним и посмотрю, смогу ли я заставить его работать, поэтому вам не нужно изобретать какие-либо колеса. – cwgem

+1

@HamishDowner Да, я дал ему шанс, но код модуля csv PyPy, даже находящийся на питоне, по-прежнему содержит много тиражей pypy. К сожалению, было бы слишком много усилий. Можете взглянуть на их [код чтения csv] (https://bitbucket.org/pypy/pypy/src/5a61eff6b57fa1bfa95bd0d04e4a9421dab987ce/pypy/module/_csv/interp_reader.py) в любом случае, если вам нужны некоторые идеи о том, как обращаться работа парсера. – cwgem

2

Я не понимаю, если у вас есть четкое представление о том, что вы пытаетесь получить..
Вы говорите «Я знаю (...) мой случай использования - это злоупотребление».
Но злоупотребление подразумевает, что существует возможность использования.
Однако в вашем случае невозможно использовать, то, что вы описали, невозможно, потому что то, что передается в синтаксический анализатор CSV, должно быть допустимым CSV-форматом, а ваше нет.

В правильной строке CSV большинство символов являются информацией, а некоторые символы являются метаинформацией, необходимой для интерпретации строки для извлечения информации.
Опишите, что вы хотите, чтобы персонажи " были в общей категории информации и метаинформации. Это похоже на тех, кто хочет поймать левую руку левой рукой.

Эта проблема возникает с вашей строкой, потому что это не строка, идущая от чтения файла CSV. Это строка, написанная как есть.
Невозможно получить такую ​​строку из чтения CSV-файла, потому что она не могла быть написана так в CSV-файле.
Если записывается в файл CSV, '"simple|split"|test' может быть написана

  • """simple|split"""|test
    с doublequote значение ИСТИНА, по умолчанию

  • или #"simple#|split#"|test
    с doublequote = False, escapechar = '#'

.

Если вы хотите, чтобы извлечь информацию, как вы описали, вы не создать парсер, вы должны просто использовать уже существующий инструмент:

import re 

reg = re.compile('".*?"|[^|]+') 

print reg.findall('yoo|"simple|split"|test|end"pos|hu') 

результат

['yoo', '"simple|split"', 'test', 'end"pos', 'hu'] 
Смежные вопросы