C#正则表达式帮助 - 使用可选数据点进行分组

时间:2018-05-30 15:28:02

标签: c# .net regex

鉴于我正在解析的2条不同的行,我需要将数据点提取到正则表达式匹配组中。

示例第1行:

标题值如下:

DATE{space}TYPE{space}DESCR{space}VOLUME{space}RATE{space}TOTAL
[11/30/15] [CF] [DISC 1] [28270.18] [0.00150] [-42.41]  

第2行示例:

DATE{space}TYPE{space}DESCR{space}VOLUME{space}RATE{space}TOTAL
[11/30/15] [CF] [OTHER VOLUME FEES] [28186.68] [0.00008] [-2.25] 

我正在使用以下正则表达式来获取匹配项:

(?<date>^\d{1,2}[-/.]\d{1,2}[-/.]\d{1,2}[\d+])\s+(?<type>[A-Za-z]{2})\s+(?<descr>\w+\s+.*?(1))\s+.*?(?<volume>(\d+(?:\.\d+?))\s+.*?(?<rate>([0]?(\d+(?:\.\d+)?)))\s+(?<total>[-+]?\d+[.,]\d+)?.*$")

我可以匹配第一种情况,但绝不是第二种情况。总会有总数,但它们可能并不总是数量或费率。另外,音量可以是整数,十进制或代码(例如“1B”)。

我在这里缺少什么?

描述字段是一个空白字段,其中可能包含“1”。我可以在其中加上几个单词,或者只是1.

2 个答案:

答案 0 :(得分:2)

您的日志行包含6个字段,但第4个和第5个字段可能会丢失。匹配可选字段的常用方法是使用可选的非捕获组(?:...)?。这些组不会为它们匹配的文本创建单独的内存缓冲区,这就是为什么它们对于保持匹配更清晰和更有效的有用。

注意在.NET中,有一种方法可以使用RegexOptions.ExplicitCapture选项使所有非命名捕获组无法捕获。

你的固定正则表达式看起来像

^(?<date>\d{1,2}[-/.]\d{1,2}[-/.]\d{1,2})\s+(?:(?<type>[A-Z]{2})\s+)?(?:(?<descr>\w.*?)\s+)?(?:(?<volume>\d*\.?\d+)\s+)?(?:(?<rate>\d*\.?\d+)\s+)?(?<total>[-+]?\d*[.,]?\d+)\s*$

请参阅.NET regex demo

enter image description here

<强>详情

  • ^ - 开始一行(使用RegexOptions.Multiline时)
  • (?<date>\d{1,2}[-/.]\d{1,2}[-/.]\d{1,2}) - 小组&#34;日期&#34;:1-2位数字,然后重复- / / / .,然后重复1-2次数字(因此,此模式可以写为(?<date>\d{1,2}(?:[-/.]\d{1,2}){2}))。
  • \s+ - 一个或多个空格
  • (?:(?<type>[A-Z]{2})\s+)? - 一个匹配2个大写ASCII字母的可选组,捕获到Group&#34; type&#34;,然后是1 + whitespaces
  • (?:(?<descr>\w.*?)\s+)? - 一个匹配单词char(字母,数字或_和其他一些特殊字符(如变音符号)的可选组,后跟除了换行符char LF之外的任何0 +字符,只有少数尽可能将所有这些捕获到Group&#34; descr&#34;,然后是1 + whitespaces
  • (?:(?<volume>\d*\.?\d+)\s+)? - 一个可选的组,匹配0+个数字,一个可选的.,然后是1+个数字(即浮点数或整数),被捕获到Group&#34; volume&#34 ;,然后1+空白字符
  • (?:(?<rate>\d*\.?\d+)\s+)? - 一个可选的组,用于匹配捕获到Group&#34; rate&#34;,然后是1+空格字符的浮点值或整数值
  • (?<total>[-+]?\d*[.,]?\d+) - 小组&#34;总计&#34;:可选-+后跟0+位数,可选.或{{1}然后1+位数(所以,正或负浮点数或整数匹配)
  • , - 任何0+尾随空格
  • \s* - 行尾。

答案 1 :(得分:0)

(?<date>^\d{1,2}[-/.]\d{1,2}[-/.]\d{1,2}[\d+])\s+(?<type>[A-Z]{2})\s+(?<descr>\w+.*?\s+)(?<volume>\d+[.]?\d+)\s+(?<rate>\d+[.]?\d+)\s+(?<total>[-+]?\d+[.,]\d+?.*$)

是。这是一个相当复杂的正则表达式。但是如果你的分组中有不同的空格,你可以使用。*?\ s +来结束最后一个空格。对于我拥有的所有用例,这似乎都很好用。

感谢您的评论!