Как обрабатывают кавычки в CSV?
Что проверяют
Знаете ли вы правила экранирования в CSV и понимаете ли, почему line.split(",") не парсер. Раз вопрос из лайвкодинга, следом часто просят разобрать строку руками, без модуля csv, и проверить решение на хитрых входах.
Как отвечать
Правила RFC 4180, на которые опирается большинство инструментов:
- когда поле берут в кавычки: если в нём есть разделитель, двойная кавычка или перевод строки;
- как экранируют кавычку: удвоением. Значение
He said "hi"записывается как"He said ""hi"""; - перевод строки внутри кавычек: часть значения, поэтому одна запись может занимать несколько физических строк файла.
В Python этим занимается модуль csv. Диалект по умолчанию excel: quotechar='"', doublequote=True, quoting=csv.QUOTE_MINIMAL, то есть кавычки ставятся только там, где нужны. Другие режимы: QUOTE_ALL, QUOTE_NONNUMERIC (при чтении превращает поля без кавычек в float), QUOTE_NONE (тогда нужен escapechar), с Python 3.12 ещё QUOTE_STRINGS и QUOTE_NOTNULL. Файл открывайте с newline='', иначе переводы строк внутри полей обработаются неверно. В pandas те же настройки есть у read_csv: quotechar, doublequote, escapechar.
Если просят парсер руками, опишите конечный автомат из трёх состояний: вне кавычек, внутри кавычек и «только что встретили кавычку внутри поля». В третьем состоянии следующая кавычка означает литерал ", разделитель закрывает поле, конец строки закрывает запись.
Где спотыкаются
Режут строку по запятым или регуляркой. Первое же поле "Москва, центр" разъезжается на два.
Путают стили экранирования и пишут \", как в JSON. Стандарт так не делает, и модуль csv без явного escapechar прочитает такое поле неверно.
Забывают про skipinitialspace: в строке a, "b" пробел перед кавычкой делает её обычным символом, и второе значение прочитается как "b", вместе с пробелом и кавычками.