问题
I am attempting to write a regex that will return a multiple line match from a log file. Using the sample below -- I want to match an entire 'transaction' which begins and ends with the same text as ALL other transactions in the log (Start and End). However - between those lines there is a custom identifier -- in this case an email address that will differentiate one transaction from another.
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.
Here is what I am starting with:
^Start(.*?)\n(((.*?)(email1\@gmail\.com)(.*?)|(.*?))\n){1,}End (.*?)\n
Essentially - I want to say: Begin with 'Start' -- and match all lines until an 'End' line, but only return a match if one of the lines contains a particular email address.
Right now -- my regex treats the entire log file as a single match since presumably line 1 contains a 'Start' and line X contains an 'End' and somewhere in the hundreds of lines in between -- their is a match for the email. Also -- application is Powershell and will be using a Select-String pattern, if that matters.
回答1:
Use a negative lookahead assertion to make sure your regex never matches across an "End of transaction" boundary:
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];
Test it live on regex101.com.
回答2:
Use s modifier to make . match newline characters:
(?s)Start((?!Start).)*email1\@gmail\.com(.*?)End([^\n]*)
Note: ((?!Start).)* asserts a negative lookahead at each position which we stepped into by * modifier to ensure that we are in one block at a single time.
Live demo
来源:https://stackoverflow.com/questions/37178732/need-regex-to-match-multiple-lines-until-match-is-found-between-common-delimiter