我正试图编写一个正则表达式,它将从日志文件中返回多行匹配。使用下面的示例——我想匹配一个完整的"事务",它以与日志中所有其他事务(开始和结束)相同的文本开始和结束。然而,在这些行之间有一个自定义标识符——在本例中是一个电子邮件地址,用于区分一个交易和另一个交易。
Start of a transaction.
random line 1.
random line 2.
email1@gmail.com
End of a transaction.
Start of a transaction.
random line 1.
random line 2.
email1@yahoo.com
random line 3.
End of a transaction.
以下是我开始的内容:
^Start(.*?)'n(((.*?)(email1'@gmail'.com)(.*?)|(.*?))'n){1,}End (.*?)'n
本质上——我想说:从"开始"开始——并匹配所有行,直到"结束"行,但只有在其中一行包含特定电子邮件地址时才返回匹配。
现在——我的regex将整个日志文件视为一个匹配项,因为第1行可能包含"Start",第X行包含"End",介于两者之间的数百行中——它们与电子邮件匹配。此外,应用程序是Powershell,如果重要的话,它将使用SelectString模式。
使用负前瞻断言来确保您的正则表达式永远不会在"事务结束"边界上匹配:
preg_match_all(
'/^ # Start of line
Start' of' a' transaction'. # Match starting tag.
(?: # Start capturing group.
(?!End' of' a' transaction) # Only match if we''re not at the end of a tag.
. # Match any character
)* # any number of times.
email1@gmail'.com # Match the required email address
(?:(?!End' of' a' transaction).)* # and the rest of the tag.
^ # Then match (at the start of a line)
End' of' a' transaction'.'n # the closing tag./smx',
$subject, $result, PREG_PATTERN_ORDER);
$result = $result[0];
在regex101.com上进行实时测试。
使用s
修饰符使.
与换行符匹配:
(?s)Start((?!Start).)*email1'@gmail'.com(.*?)End([^'n]*)
注意:((?!Start).)*
在我们通过*
修饰符进入的每个位置上断言一个负前瞻,以确保我们一次处于一个块中
实时演示