Как я могу проанализировать отформатированные и напечатанные текстовые таблицы человека с большим количеством вариаций в Java, и если регулярное выражение является ответом, как правильно получить значения строк? - PullRequest
4 голосов
/ 01 октября 2019

Я должен проанализировать чрезвычайно разнообразный пользовательский ввод. Примером может быть:

Example 1:
March
    Morning     Evening
    (Avg Count) (Avg Count)
Birds    5.6          10.35
Mammals  2.0          3.3


Example 2:
March
    Morning   Afternoon Evening
     (Num)     (Num)     (Num)
Birds    5.6       9        10
Mammals  2.0       2.5      3.3
Reptiles 1.0       5.6      1.75

Status Avg Total: Birds 24
Concerning that numbers have dwindled since last year

Example 3:
    Early     Mid       Late 
    (Count)   (Count)   (Count)
Mammal   2.0       2.5      3.3  (Count)
Reptile 1.0    5.6      1.75  (Count)

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

Моя текущая стратегия заключается в использовании классов соответствия Java классов Java. Я использую matcher.matchers () , чтобы проверить, является ли форматирование заголовка возможным форматом. Исходя из этого, я отправляю текст методу, который использует matcher.find () для получения групп захвата из строки. Это вытащит имя строки (например, млекопитающее) и значения скажут 2.0 и 3.3 из первого примера из текста. Однако пользовательский ввод настолько разнообразен, что этот метод очень привередливый.

Например, я изначально вытаскивал Birds 24 из примера 2 в качестве группы захвата, потому что в тексте он содержит формат, аналогичный столбцу. Поэтому я изменил его, чтобы не допустить текст, кроме имени строки в строке. Однако теперь он не может извлекать строки, подобные примеру 3, с (Count) рядом с ним.

Так что мой текущий подход заключается в проверке формата заголовка с помощью регулярных выражений. Если формат, вытащите имя строки и значения. Даже с этой стратегией у меня возникают проблемы с поиском правильного регулярного выражения, чтобы получить строку правильного ряда и значений.

Мое текущее регулярное выражение для matcher.find () таково:

(Mammal|Reptile|Bird|Mammals|Reptiles|Birds)(^a-zA-Z-]*?[0-9])\r\n|[\r\n]

Где группа захвата 1 будет именем строки, а группа 2 должна быть числами

Итак, у меня два вопроса:

Есть ли лучший способ решения этой проблемы?

Если нет лучшего способа, что быбыть правильным выражением регулярного выражения, чтобы вытащить строку и ее значения?

1 Ответ

1 голос
/ 02 октября 2019

Вы можете использовать 2 группы захвата, где первая содержит имя строки, например, «Птицы», и повторное совпадение для группы 2, которая содержит числа с использованием якоря \G.

Обратите внимание, что вы можете добавить необязательный sиспользование s? для сопоставления с Mammal или Mammals и т. д.

(?:^(Mammals?|Reptiles?|Birds?)|\G(?!^))\h+(\d+(?:\.\d+)?)
  • (?: Группа без захвата
    • ^ Утверждение начала строки
    • (Mammals?|Reptiles?|Birds?) Захват группа 1 соответствует любому варианту
    • | Или
    • \G(?!^) Утверждение позиции в конце предыдущего матча
  • ) Закрыть группу без захвата
  • \h+ Совпадение с 1 + горизонтальными пробелами
  • ( Захват группа 2
    • \d+(?:\.\d+)? Совпадение 1+ цифр и необязательная часть для сопоставления десятичных знаков
  • ) Закрыть группу 2

Regex demo | Java demo

В Java

final String regex = "(?:^(Mammals?|Reptiles?|Birds?)|\\G(?!^))\\h+(\\d+(?:\\.\\d+)?)";

Обратите внимание , что вместо использования \d+(?:\.\d+)? для сопоставления цифр, вы могли бы использовать \S+ создать широкое совпадение, соответствующее 1+ раз непробельному символу.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...