正则表达式匹配特定字符串之后的所有行

标签 regex

可能与 Regex - find all lines after a match: 重复虽然我的需求有点不同。

我想解析一个纯文本文件,其中包含由特定字符串分隔的多个日期/值数据。我想跳过文件的前半部分,直到我想要匹配结果的特定行。

以下是相关文件的示例(包括困惑的表格和空格):

   I dont want to capture the following measures. This  text is     on a single line and        contains tabs and spaces    is also ends with this token : Token1
05/01/1969         0.01846  
15/01/1969         0.16730  
25/01/1969         0.33988  
05/04/1969         0.81319  
15/04/1969         0.76973  
25/11/2011             0.24210
05/12/2011             0.25220
15/12/2011             0.31160
25/12/2011             0.36845
            End :  bla bla bla
   This text        is also on a single line        and marks the beginning of a new series of      results. These are the results that I want. it also ends with the following         token : Token2
05/01/1969       109.46333  
15/01/1969       110.06998       118.18000
25/01/1969       110.82954  
05/02/1969       111.51394       118.83000
25/02/1969       112.36483  
05/10/2011       114.38798       114.31000
05/10/2011           114.31000       114.38798       114.38798       114.38798       114.38798       114.38798       114.38798
25/12/2011           112.64000       112.41261       112.86301       113.25494       114.06421       115.93219       116.38780
05/01/2012               112.22834       112.92301       113.40561       114.78823       116.62931       117.43421
05/09/2012               110.01410       112.16391       112.88199       115.23640       117.04756       118.04632
15/09/2012               109.97572       112.00809       112.70266       114.91247       116.65256       117.57412
25/09/2012               109.93967       111.87272       112.53305       114.60381       116.26935       117.12756 
            End :  Marks the    end of          the      file

我想要做的是匹配以 Token2 结尾的行之后的每一行。我尝试了其他类似问题的不同解决方案,但没有成功。我最终匹配了文件的所有结果,并考虑在应用以下模式之前将其拆分。有没有一个纯粹的正则表达式解决方案?

这是适用于整个文件的模式。使用命名捕获组:

(?P<date>\d\d\/\d\d\/\d\d\d\d)\s*(?P<simul>\d+\.*\d*)[\t ]*(?P<observ>\d+\.*\d*){0,1}[\t ]*(?P<prev_no_rain>\d+\.*\d*){0,1}[\t ]*(?P<prev_10_dry>\d+\.*\d*){0,1}[\t ]*(?P<prev_20_dry>\d+\.*\d*){0,1}[\t ]*(?P<prev_50>\d+\.*\d*){0,1}[\t ]*(?P<prev_20_wet>\d+\.*\d*){0,1}[\t ]*(?P<prev_10_wet>\d+\.*\d*){0,1}

Regex101 链接:https://regex101.com/r/a0mCZ2/3

最佳答案

您可以利用\G匹配字符串开头(可以通过否定查找排除)和上一个成功匹配位置结尾的运算符。随着(?:\G(?!\A)|\bToken2[\r\n]+)我们可以告诉正则表达式引擎查找整个单词 Token2位于行尾(带有换行符号),然后仅找到紧随其后的以下子模式。

可以使用的正则表达式:

(?:\G(?!\A)[\r\n]*|Token2[\r\n]+)\K(?P<date>\d\d\/\d\d\/\d{4})\s*(?P<simul>\d+\.*\d*)[\t ]*(?P<observ>\d+\.*\d*)?[\t ]*(?P<prev_no_rain>\d+(?:\.\d+)*)?[\t ]*(?P<prev_10_dry>\d+\.*\d*)?[\t ]*(?P<prev_20_dry>\d+\.*\d*)?[\t ]*(?P<prev_50>\d+\.*\d*)?[\t ]*(?P<prev_20_wet>\d+\.*\d*)?[\t ]*(?P<prev_10_wet>\d+\.*\d*)?

请参阅regex demo 。注意我替换了{0,1}?稍微缩短一下。

您感兴趣的部分是(?:\G(?!\A)[\r\n]*|Token2[\r\n]+)\K

  • (?:\G(?!\A)[\r\n]*|Token2[\r\n]+) - 两种选择之一:
    • \G(?!\A)[\r\n]* - 上一次成功匹配的结束和 0+ 换行符号
    • | - 或
    • Token2[\r\n]+ -Token2随后是 1+ CR 或 LF。 (如果您需要将 Token2 作为整个单词进行匹配,您可以在其前面添加 \b)。
  • \K - 省略目前匹配的文本。

(?P<date>\d\d\/\d\d\/\d{4})\s*(?P<simul>\d+\.*\d*)[\t ]*(?P<observ>\d+\.*\d*)?[\t ]*(?P<prev_no_rain>\d+(?:\.\d+)*)?[\t ]*(?P<prev_10_dry>\d+\.*\d*)?[\t ]*(?P<prev_20_dry>\d+\.*\d*)?[\t ]*(?P<prev_50>\d+\.*\d*)?[\t ]*(?P<prev_20_wet>\d+\.*\d*)?[\t ]*(?P<prev_10_wet>\d+\.*\d*)?是我没有修改太多的模式,并且它与具有特定 fata 的行匹配(请注意,它与行匹配这一事实证明了在 [\r\n]* 之后使用 (\G(?!\A)) 是合理的)。

关于正则表达式匹配特定字符串之后的所有行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40041546/

相关文章:

regex - HTML5 浏览器密码验证(有效模式属性!): minimum 6 chars and at least 1 number and 1 Capital letter

java - 如何使用正则表达式在同一行捕获可变数量的模式?

python - 获取所有距离一个字符的字符串?

javascript - 如果字符串包含数值,则从字符串中删除整个单词

c# - 正则表达式匹配单行或多行中的任何单词 [\r\n]

电子邮件验证正则表达式的java代码

c# - 无法理解为什么正则表达式不适用于字符串的开始/结束标记

java - MongoDB $regex 查询 "end with"特定字符

java - 使用 Java 获取 CSS 文件中图像的 URL?

ruby - 在 Nokogiri 元素中编辑文本或使用正则表达式