Разделение строки в Java, игнорируя запятые в кавычках
Пройдите тест, узнайте какой профессии подходите
Быстрый ответ
Чтобы разделить строку, содержащую запятые, исключая те, что находятся в кавычках, возможно использовать регулярное выражение ,(?=(?:[^"]*"[^"]*")*[^"]*$)
в паре с методом String.split()
в Java:
String input = "one,\"two,2\",three";
String[] result = input.split(",(?=(?:[^"]*\"[^"]*\")*[^"]*$)");
В итоге мы получаем массив: ["one", "\"two,2\"", "three"]
. Здесь используется такая техника как положительный просмотр вперёд (lookahead), которая позволяет игнорировать запятые, следующие за четным числом кавычек.
Подробнее о регулярных выражениях
Разбор работы регулярного выражения
Приведенное регулярное выражение отлично справляется с простыми CSV-строками. Оно разделяет строку по запятым, четное количество кавычек после которых гарантируется с помощью положительного просмотра вперёд (?= ...)
.
Более сложные случаи и регулярные выражения
Если вам предстоит разбирать многоуровневые строки или кавычки в кавычках, стоит рассмотреть применение лексического анализатора, учитывающего состояния. Для этого может оказаться полезным StringBuilder
— поточный инструмент для работы со строками.
Использование сторонних библиотек
В случаях работы со сложными данными могут быть полезны такие библиотеки как Apache Commons CSV, OpenCSV или JavaCSV-Reloaded, разработанные специально для обработки CSV-строк.
Производительность против поддерживаемости
Не стоит забывать, что регулярные выражения часто могут быть не самым эффективным способом разбора CSV. Профессиональные библиотеки, предлагающие более высокую читаемость кода и расширенные возможности, могут значительно упростить процесс разработки.
Визуализация
Представьте вагон, разделенный на отсеки с помощью дверей-запятых:
Вагон: [🍻, 🍗, "🎂, 🍷", 🎈 ]
Запятыми здесь являются двери, не препятствующие движению внутри кавычек. Применим наш код:
String[] splitTrain = train.split(",(?=(?:[^"]*\"[^"]*\")*[^"]*$)");
Разделение проходит без нарушения покоя:
Компартменты вагона: [🍻] [🍗] ["🎂, 🍷"] [🎈 ]
# Запятые внутри кавычек действуют по-своему, поддерживая целостность отсека. Все продолжают путешествие, правильно?
Эта модель отразила принцип разбиения строки с учетом запятых внутри кавычек.
Когда регулярные выражения не справляются
Ручной парсинг для сложных случаев
В случае, когда структура данных усложнена вложенными кавычками или экранированными символами, может потребоваться ручной парсинг. Разработка простого конечного автомата позволит контролировать контекст при прохождении по символам строки.
Техника замены
Запятые внутри кавычек можно заменить на другой символ-заполнитель, затем разделить строку и в последующем вернуть запятые на их место. Это немного напоминает волшебный трюк в мире программирования.
Оптимизация производительности
Если производительность является важным фактором, предпочтение можно отдать использованию StringBuilder
перед StringBuffer
за счет меньшей синхронизационной нагрузки.
Полезные материалы
- Java: как разбить строку с запятыми, игнорируя запятые в кавычках – Stack Overflow — подробное обсуждение и решения для разбора CSV в Java.
- Pattern (Java Platform SE 8) — официальная документация Java по классу Pattern, разъясняющая основные концепции и методы работы с регулярными выражениями.
- Разделение по запятой вне кавычек – Stack Overflow — дополнительные примеры и объяснения использования регулярных выражений для разбиения CSV.
- Урок по регулярным выражениям: Просмотры вперёд и назад — детальное руководство по применению просмотра вперёд и назад в регулярных выражениях, важно при игнорировании запятых после кавычек.
- Commons CSV – Главная страница — официальная страница библиотеки Apache для работы с CSV, предлагающей функции высокого уровня.
- GitHub – super-csv/super-csv: функциональная CSV библиотека для Java – гибкая библиотека для обработки CSV-данных в сложных ситуациях.
- Чтение и запись CSV файлов в Java — практические примеры по работе с CSV в Java, представлены на сайте Baeldung.