Java: поиск элегантного способа разбить строку

Я знаю, что есть много вопросов и ответов на темы, связанные с регулярными выражениями, и я уже прочитал много из них и сам пробовал несколько способов, но все они кажутся непростыми для понимания. Поэтому я хотел спросить, может ли кто-нибудь помочь мне сделать это лучше?

Моя проблема

Я получаю строку, которая выглядит так (это строка в немецком формате):

"[Header: 150,00;20.02.2019;Bemerkung\]\;;\;Andere Bemerkung;]"

Как вы можете видеть, разные столбцы разделены точкой с запятой ;, но, к сожалению, символы точки с запятой также разрешены в полях комментариев (например, \;Andere Bemerkung) и, таким образом, экранируются (с помощью \ исходной системой, из которой я получаю доставленную строку.

Теперь моя задача состоит в том, чтобы проверить правильность количества столбцов в этой строке, но не изменять саму строку. В этом случае количество столбцов должно быть 5

Мое текущее решение

Поскольку я плохо разбираюсь в регулярных выражениях, и времени мало, чтобы стать экспертом в решении этой проблемы, я использую разные Java API для разделения строки:

"[Header: 150,00;20.02.2019;Bemerkung\\]\\;;\\;Andere Bemerkung;]".replace("\\;", " ").split(";")

Я использую replace API, потому что он не принимает регулярное выражение, а просто String в качестве аргумента, поэтому я могу заменить \; пробелом, а затем успешно разбить строку на столбцы, и я могу проверить результат. Поскольку строки неизменяемы, это работает нормально, но решение выглядит так, как будто в Java есть лучшие способы сделать это.

Я также искал в API apache-commons-lang и apache-commons-текст, а также в предоставленных API весенний ботинок, но не смог найти лучшего решения.

Я также пробовал регулярное выражение с черным списком выражений, потому что в моем случае этот черный список был бы очень коротким, но, к сожалению, я думаю, что даже не приблизился к решению.

У вас есть лучшее решение?

Вы можете разделить, используя регулярное выражение tis (?<!\\);

anubhava 17.06.2019 16:15

Хотя это широко распространено, я считаю плохой практикой разбивать строку только для подсчета появления данной подстроки/символа, когда вы выделяете массив строк только для вызова .length. Если вы действительно хотите только проверить количество столбцов, используйте что-то вроде apache commons и выполните count(";") - count("\\;"). Это просто и скучно, и это лучший вид кода :) (по сравнению с регулярным выражением с возвратом)

roookeee 17.06.2019 16:16
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
2
2
503
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Прежде всего, если вы не экранируете обратную косую черту или в строке не может быть буквальных обратных косых черт, вы можете разделить ее с помощью ;, которому не предшествует \:

s.split("(?<!\\\\);")

Если могут быть какие-либо экранированные объекты, используйте

(?:[^;\\]|\\.)++

регулярное выражение для соответствовать обязательных полей. См. эта демонстрация регулярных выражений. (?:[^;\\]|\\.)++ будет соответствовать 1 или более повторениям любого символа, кроме ; и \ или \, за которым следует любой символ. Скомпилируйте шаблон с флагом Pattern.DOTALL, если в содержимом для разделения могут быть разрывы строк.

Демонстрация Java:

String s = "[Header: 150,00;20.02.2019;Bemerkung\\]\\;;\\;Andere Bemerkung;]";
List<String> result = new ArrayList<>();
Pattern pattern = Pattern.compile("(?:[^;\\\\]|\\\\.)++");
Matcher matcher = pattern.matcher(s);
while (matcher.find()){
    result.add(matcher.group(0)); 
} 
System.out.println(result);
// => [[Header: 150,00, 20.02.2019, Bemerkung\]\;, \;Andere Bemerkung, ]]

Другие вопросы по теме