Мне нужно проанализировать текстовый файл по запятой, а не по запятой в кавычках.
Это выглядит как тривиальная задача, но заставить Python сделать ее правильно невозможно. В основном из-за того, что перед строкой в кавычках стоит строка без кавычек, из-за чего CSV, вероятно, не очень хорошо отформатирован, но мне это нужно именно так.
Пример ввода:
cmd,print "AA"
cmd, print "AA,BB,CC"
cmd, print " AA, BB, CC ", separate-window
Желаемый результат (в синтаксисе Python):
[['cmd', 'print "AA"'],
['cmd', 'print "AA,BB,CC"'],
['cmd', 'print " AA, BB, CC "', 'separate-window']]
Удаление окружающих пространств не является обязательным, как только я получу правильный список, я смогу strip()
каждый элемент, это не проблема.
csv.reader
также разделяется запятыми в кавычках, так что я предпочитаю получать ['cmd', 'print "AA', 'BB', 'CC"']
.
shlex
с измененными .whitespace=','
и .whitespace_split=True
почти помогает, но удаляет кавычки ['cmd', 'print AA, BB, CC']
. Мне нужно сохранить кавычки.
Думал о re.split
, но у меня очень слабое представление о том, как работает (?=)
штука...
Нашел здесь несколько похожих тем, но ни один из предложенных ответов мне не помог.
ОБНОВЛЕНИЕ: скриншот для тех, кто сомневается, делаю ли я именно то, что описываю:
Точный входной файл, который я предоставил. Точный код: с open(test_list_name) как csvfile: rtl_data = csv.reader(csvfile, delimiter=',', quotechar='"', Skipinitialspace=True) для дополненной_строки в rtl_data: row = tuple(cell.strip() для ячейка в Padded_row)
Кавычки должны быть вокруг всего поля. Кавычки в середине поля не имеют особого значения.
@Jean-BaptisteYunès Как это поможет? Во входном файле нет символов '
.
Это недопустимый файл CSV.
Если вы не можете исправить входной файл, вам нужно будет написать собственный синтаксический анализатор, который проверяет наличие двойных кавычек. Я не думаю, что вы можете сделать это с помощью регулярного выражения, они плохо различают «внутренние кавычки» от «внешних кавычек».
@Barmar да, я сказал в вопросе: «Возможно, это не очень хорошо отформатированный CSV, но мне он нужен именно такой». Это заставляет меня сомневаться в том, что вы проверяли мой реальный пример ввода.
Что ты имеешь в виду? Я удалил свой комментарий о том, что получил желаемый результат, потому что посмотрел еще раз и увидел, что это неправильно.
@barmar прочитал слишком быстро...
@JohnGordon вот скриншот i.sstatic.net/nMMxT.png, ясно, что программа чтения csv НЕ делает то, что мне нужно. Хотелось бы увидеть скриншот, подтверждающий ваши слова.
Я неправильно понял вывод, когда запускал ваш код, и удалил свой предыдущий комментарий. Бармар прав, это неверный файл CSV. Вы не можете заключать в кавычки только часть столбца, весь столбец должен быть в кавычках.
@JohnGordon задолго до того, как «Бармар был прав», я написал точно то же самое в своем вопросе - это неправильно сформированный CSV. К счастью, его комментарий о «внутренних кавычках» дал мне подсказку, что гуглить, и я нашел решение.
Вероятно, вам придется обрабатывать эти данные самостоятельно. Мне удалось добиться желаемого результата с помощью следующей функции:
def parse_line(line: str) -> list[str]:
in_quote = False
start = 0
output = []
stripped_line = line.strip()
for index, char in enumerate(stripped_line):
if char == '"':
in_quote = not in_quote
if char == ',' and not in_quote:
output.append(stripped_line[start:index])
start = index + 1
else:
if index + 1 != start:
output.append(stripped_line[start:len(stripped_line)])
return output
for line in csvfile:
print(parse_line(line))
['cmd', 'print "AA"']
['cmd', ' print "AA,BB,CC"']
['cmd', ' print " AA, BB, CC "', ' separate-window']
Написание собственного парсера — всегда очевидный вариант, но мне не хотелось изобретать колесо, если оно уже изобретено.
Погуглив еще немного и удалив слово «python» из запроса, я нашел решение. По какой-то теме, связанной с Java, был задан очень похожий вопрос. И ответ был: использовать regex
.
Итак, я настроился на Python и вот точный код, который мне подходит:
import re
splitter = re.compile(r',(?=(?:[^"]*"[^"]*")*[^"]*$)')
with open('example.txt') as csvfile:
for padded_row in csvfile:
stripped_row = padded_row.rstrip()
row = splitter.split(stripped_row)
print(row)
Подробное объяснение, как это работает
Спасибо комментаторам, вы действительно дали мне несколько подсказок, как улучшить мои запросы в Google :)
csv.reader тоже разделяется запятыми в кавычках. Это не должно быть. Пожалуйста, покажите нам точный код, который вы использовали, и точный входной файл.