Need Regex to match multiple lines until Match is found between common delimiters

余生长醉 提交于 2019-12-11 07:59:02

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!