The example
(?<log>(?<ymdhm>\d{4}-\d{2}-\d{2} \d{2}:\d{2}).*?(?<flag>Starting)$)\n\k<ymdhm>.*?\k<flag>
[更新]
好吧,我更新了正则表达式,这并不容易。
以下是说明:
-
组“ log”根据您的基本规则匹配一行。它分为几个部分:
-
(?<ymdhm>\d{4}-\d{2}-\d{2} \d{2}:\d{2})
“ ymdhm” YY-MM-DD HH:MM,这是为以后的匹配而导入的,因为您需要注意直到数分钟的时间数字,所以下一个合格的行必须具有完全相同的模式。
-
(?<flag>Starting)$
“标志”是导入模式,这就是您要查找的内容,即“标志”。
-
.*?
在它们之间的中间是您不太在乎的字符。
-
然后,它必须有另一行\n
。此处,regexp使用标志gm
。如果没有\n
,它将停止检查以下行。
-
\k<ymdhm>
意味着应用与最后一组“ ymdhm”相同的模式,这意味着下一个日志的时间应具有相同的数字。 Explanation代表\k
。
- 然后懒惰地匹配任意字符。
- 然后
\k<flag>
与上一个匹配的标志模式匹配。
,
(?:^|\n)(\d{4}(?:-\d{2}){2} (?:\d{2}:){2})\d{2}\.\d{3}( [+-]\d{2}:\d{2} )\[\d+\]( - Starting)[^\n]*(\n\1\d{2}\.\d{3}\2\[\d+\]\3[^\n]*)+
Give it a whirl
注意:
- 这不能容忍间距上的偏差(您只需要用
替换所有\s+
即可)
- 将仅匹配重复的块,而不是每个重复的单个块(在您的示例中,一个匹配项,包含两行)
- 仅当顺序重复时才能识别重复项(这是为了保持正则表达式的效率)
我不同意@ggorlen的评估,对于需要这种表达能力的问题,正则表达式实际上是您可以做的最快的事情。
但是,如果您需要匹配不连续的“开始”行,但是则可以保证按顺序排列(基本上对于所有日志来说都是这样,同一分钟的“开始”行和非“开始”行都将彼此相邻),我们可以对此进行调整并仍然保持合理高效:
(?:^|\n)(\d{4}(?:-\d{2}){2} (?:\d{2}:){2})\d{2}\.\d{3}( [+-]\d{2}:\d{2} )\[\d+\]( - Starting)[^\n]*(?:\n\1\d{2}\.\d{3}\2\[\d+\][^\n]*)*\n\1\d{2}\.\d{3}\2\[\d+\]\3[^\n]*
Have a play,以确保它可以满足您的需求
具有与b̲l̲o̲c̲k̲s̲匹配的相同警告,因此,匹配“起始”行之间的非起始行仍将匹配。
为了提高效率以使每行单独匹配,我们可以对这两个半部使用超前/后退。
我们需要复制正则表达式以捕获块的不同末端。
Some browsers wont even let you do crazy stuff like this,即使Chrome不能使所有在线测试人员都let me give you a breakdown of the resulting regex
(?:^|\n)(\d{4}(?:-\d{2}){2} (?:\d{2}:){2})\d{2}\.\d{3}( [+-]\d{2}:\d{2} )\[\d+\]( - Starting)[^\n]*(?=(?:\n\1\d{2}\.\d{3}\2\[\d+\][^\n]*)*\n\1\d{2}\.\d{3}\2\[\d+\]\3[^\n]*)|(?<=(?:^|\n)(\d{4}(?:-\d{2}){2} (?:\d{2}:){2})\d{2}\.\d{3}( [+-]\d{2}:\d{2} )\[\d+\]( - Starting)[^\n]*(?:\n\4\d{2}\.\d{3}\5\[\d+\][^\n]*)*)\n\4\d{2}\.\d{3}\5\[\d+\]\6[^\n]*
幸运的是,PowerShell(正如您在评论中提到的那样)仍然可以很好地处理它,但是我敢肯定,对于大型日志文件,PowerShell会停止运行。
(
([regex](
(
'(?:^|\n)(\d{4}(?:-\d{2}){2} (?:\d{2}:){2})\d{2}\.\d{3}( [+-]\d{2}:\d{2} )\[\d+\]( - Starting)[^\n]*(?=(?:\n\1\d{2}\.\d{3}\2\[\d+\][^\n]*)*\n\1\d{2}\.\d{3}\2\[\d+\]\3[^\n]*)','(?<=(?:^|\n)(\d{4}(?:-\d{2}){2} (?:\d{2}:){2})\d{2}\.\d{3}( [+-]\d{2}:\d{2} )\[\d+\]( - Starting)[^\n]*(?:\n\4\d{2}\.\d{3}\5\[\d+\][^\n]*)*)\n\4\d{2}\.\d{3}\5\[\d+\]\6[^\n]*'
) -join '|')
).Matches((
'2019-10-31 05:49:52.416 +10:00 [1] - Starting','2019-10-31 05:49:53.416 +10:00 [2] - not starting','2019-10-31 05:49:53.416 +10:00 [2] - Starting','2019-10-31 05:49:53.416 +10:00 [3] - Starting','2019-10-31 06:53:58.416 +10:00 [1] - Starting','2019-10-31 06:53:58.416 +10:00 [1] - Identical but not "starting"'
) -join "`n")
).Value
,
您可以使用backreference来捕获以下所有行中认为相同的时间戳部分,并且还可以在第二次捕获中捕获Starting
的一部分组。
然后,您可以重复匹配以与组1相同的值开始并在行中包含组2的所有行。
^(\d{4}-\d{2}-\d{2} \d{2}:\d{2}).*(\bStarting\b)(?:\R\1.+\2)+
-
^
行的开头
-
(
捕获第1组
-
\d{4}-\d{2}-\d{2} \d{2}:\d{2}
与您要捕获的类似时间戳的格式匹配
-
)
关闭群组
-
.+
匹配除换行符1次以上以外的所有字符
-
(
捕获第2组
-
)
关闭群组
-
(?:
非捕获组
-
\R\1.+\2
匹配Unicode换行符序列,对第1组中捕获的内容的反向引用是除换行符以外的任何字符的1倍以上,对第二组中捕获的内容的反向引用
-
)+
关闭非捕获组并重复1次以上以匹配至少2行
Regex demo
本文链接:https://www.f2er.com/2909295.html