如何在 Java 中解析具有大量变体的人类格式化和类型化的文本表,如果正则表达式是答案,如何正确获取行值?



我必须解析一个极其多样化的用户输入。一个例子是:

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 的模式匹配器类。 我正在使用matcher.matchers((来测试标头的格式是否 是一种可能的格式。基于此,我将文本发送到使用matcher.find((的方法 从行中获取捕获组。它会拉出行名(例如哺乳动物(和值 比如说 2.0,以及文本中第一个示例的3.3。但是,用户输入是如此多样化, 这种方法非常挑剔。

例如,我最初是从示例中拉出Birds 242 作为捕获组,因为在文本中它包含与列类似的格式。所以我将其更改为不允许任何文本,但行中的行名除外。但是,现在它无法像示例一样拉出行 3 旁边有(计数(。

所以我目前的方法是,使用正则表达式检查标头格式。如果是格式,请拉取 出行名称和值。即使使用这种策略,我也很难找到正确的正则表达式 获取行正确的行和值。

我目前对matcher.find((的正则表达式是这样的:

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

其中捕获组 1 是行名,组 2 应该是数字

所以我有两个问题:

有没有更好的方法来解决这个问题?

如果没有更好的方法,那么提取行及其值的正确正则表达式是什么?

您可以使用2 个捕获组,其中第一个组包含行名称(如 Birds(,而组 2 的重复匹配包含使用G锚点的数字。

请注意,您可以使用s?添加可选的 s 以匹配哺乳动物或哺乳动物等。

(?:^(Mammals?|Reptiles?|Birds?)|G(?!^))h+(d+(?:.d+)?)
  • (?:非捕获组
    • ^断言字符串的开头
    • (Mammals?|Reptiles?|Birds?)捕获组 1匹配任何选项
    • |
    • G(?!^)在上一场比赛结束时断言位置
  • )关闭非捕获组
  • h+匹配 1+ 水平空格字符
  • (捕获组 2
    • d+(?:.d+)?匹配 1+ 位数字和匹配小数的可选部分
  • )关闭组 2

正则表达式演示 |爪哇演示

在爪哇语中

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

请注意,您可以使用S+创建与非空格字符匹配 1+ 倍的广泛匹配,而不是使用d+(?:.d+)?来匹配数字。

相关内容

最新更新