可能与 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/