正则表达式可选组捕获值

时间:2015-09-23 00:55:45

标签: regex conditional inline optional lookahead

我在使用Regex提取不规则数据时遇到了困难。我尝试使用Lookhead但是当值不存在时,整个匹配返回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值并将其分配给Row在下面实现,但如果值R03不存在于字符串中,则整个匹配返回false

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

了解如何使这些正则表达式语句可选,允许我返回以下内容

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]+)

感谢您的帮助

-Edited 感谢Jorge的快速回复

输入数据将是     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。

1 个答案:

答案 0 :(得分:0)

我确信通过char解析char并存储每个值会更容易。

至于正则表达式问题,基本上你要做的就是创建所有组,就像你已经尝试过一样,但你也想让它们成为可选组,因为并非所有组都可以在那里。

您可以使用以下构造使组成为可选项:

(?: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