带值的正则表达式可选组捕获

Regex Optional Groups Captures with Values

我在使用 Regex 提取不规则数据时遇到困难。我尝试使用 Lookheads,但是当该值不存在时整个匹配 returns false。数据集一直是一致的,直到我到达以 RXX 开头的字符。 RXX 是唯一标识符(组),每组 Rxx 之间的数值是我想要捕获的并将它们分配给组名。

Rxx 值从 R01 到 R15 是随机的,字符串中可以存在 1 到所有 15。

字符串值可能不同于

12*000000000**S304JB01811*8*0*8*4*4*34R0332R152~~~
12*000000000**S304JB01811*9*0*4*3*4*224R023R032R10234R1325~~~

我能够提取值并分配组名,直到到达 Rxx 我的尝试是提取值如下

S304JB0...(?<Total1>[\d]+).(?<Total2>[\d]+).(?<Total3>[\d]+).(?<Total4>[\d]+).(?<Total5>[\d]+).(?<Total6>[\d]+).(?<Total7>[\d]+)

这给了我下面想要的东西

Total1  `1`
Total2  `8`
Total3  `0`
Total4  `8`
Total5  `4`
Total6  `4`
Total7  `34`

下面实现了捕获 R03 值并将其分配给行,但如果字符串中不存在值 R03,则整个匹配 returns false

(?<Row3>(R03)[\d]+)

看看如何使这些正则表达式语句成为可选的,从而允许我return以下

Total1  `1`
Total2  `8`
Total3  `0`
Total4  `8`
Total5  `4`
Total6  `4`
Total7  `34`
Row1    `32`
Row15   `2`

S304JB0...(?<Total1>[\d]+).(?<Total2>[\d]+).(?<Total3>[\d]+).(?<Total4>[\d]+).(?<Total5>[\d]+).(?<Total6>[\d]+).(?<Total7>[\d]+)(?<Row3>(R03)[\d]+)(?<Row4>(R04)[\d]+) ------>  (?<Row15>(R15)[\d]+)

感谢您的帮助

-已编辑 感谢乔治的快速回复

输入数据将是 12*000000000**S304JB01811*8*0*8*4*4*34R0332R152~~~

输出将是9个捕获组结果

 Group | Result

 Total1 = 1
 Total2 = 8
 Total3 = 0
 Total4 = 8
 Total5 = 4
 Total6 = 4
 Total7 = 34
 Row1   = 32
 Row15  = 2

我的示例在下面与输入和 https://regex101.com/r/wG3aM3/68

希望这有助于澄清事情 D.

我敢肯定这会更容易逐个解析一个字符并存储每个值。

至于正则表达式问题,基本上您想要做的是创建所有组,就像您已经尝试过的那样,但您还希望将它们设为可选,因为可能并非所有组都在那里。

您可以使用如下构造使组可选:

(?:R01(?<Row1>\d+))?

因此您应该添加每一个以获取不同捕获组中的值。请注意,我使用了与组完全相同的构造 (?:non-capturing),但它不会创建反向引用。你可以阅读它 here.

编辑: 还有一件事。您正在使用 . 来允许任何定界符。但是,在性能方面,最好使用 \D 之类的东西(数字除外)。在失败的情况下,它为正则表达式引擎节省了很多回溯步骤。

这将是整个表达式,假设 Rxx 组总是有序的。

S304JB0...(?<Total1>\d+)\D(?<Total2>\d+)\D(?<Total3>\d+)\D(?<Total4>\d+)\D(?<Total5>\d+)\D(?<Total6>\d+)\D(?<Total7>\d+)(?:R01(?<Row1>\d+))?(?:R02(?<Row2>\d+))?(?:R03(?<Row3>\d+))?(?:R04(?<Row4>\d+))?(?:R05(?<Row5>\d+))?(?:R06(?<Row6>\d+))?(?:R07(?<Row7>\d+))?(?:R08(?<Row8>\d+))?(?:R09(?<Row9>\d+))?(?:R10(?<Row10>\d+))?(?:R11(?<Row11>\d+))?(?:R12(?<Row12>\d+))?(?:R13(?<Row13>\d+))?(?:R14(?<Row14>\d+))?(?:R15(?<Row15>\d+))?

DEMO