2016-05-12 3 views
1

Ich versuche, eine Regex zu schreiben, die eine mehrzeilige Übereinstimmung aus einer Protokolldatei zurückgibt. Mit dem folgenden Beispiel möchte ich eine ganze 'Transaktion' abgleichen, die mit dem gleichen Text beginnt und endet wie ALLE anderen Transaktionen im Protokoll (Start und Ende). Zwischen diesen Zeilen gibt es jedoch eine benutzerdefinierte Kennung - in diesem Fall eine E-Mail-Adresse, die eine Transaktion von einer anderen unterscheidet.Regex muss mit mehreren Zeilen übereinstimmen, bis Übereinstimmung zwischen gemeinsamen Begrenzern gefunden wird

Start of a transaction. 
random line 1. 
random line 2. 
[email protected] 
End of a transaction. 
Start of a transaction. 
random line 1. 
random line 2. 
[email protected] 
random line 3. 
End of a transaction. 

Hier ist, was mit Ich beginne:

^Start(.*?)\n(((.*?)(email1\@gmail\.com)(.*?)|(.*?))\n){1,}End (.*?)\n 

Im Wesentlichen - ich will sagen: mit ‚Start‘ Start - und alle Zeilen entsprechen, bis ein ‚Ende‘ Linie, sondern nur Rückkehr eine Übereinstimmung, wenn eine der Zeilen eine bestimmte E-Mail-Adresse enthält.

Gerade jetzt - meine Regex behandelt die gesamte Protokolldatei als eine einzige Übereinstimmung, da vermutlich Zeile 1 enthält ein "Start" und Zeile X enthält ein "Ende" und irgendwo in den Hunderten von Zeilen dazwischen - ihre ist a passen Sie für die E-Mail an. Auch - Anwendung ist Powershell und wird ein Select-String-Muster verwenden, wenn das wichtig ist.

Antwort

2

Verwenden Sie ein negative lookahead assertion um sicherzustellen, dass Ihre Regex passt nie über ein „Ende der Transaktion“ Grenze:

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. 
    [email protected]\.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]; 

Testen Sie live on regex101.com.

0

Verwenden s Modifikator . Spiel Zeilenumbrüche zu machen:

(?s)Start((?!Start).)*email1\@gmail\.com(.*?)End([^\n]*) 

Hinweis: ((?!Start).)* behauptet eine negative Vorschau an jeder Position, die wir in abgestuften durch * Modifikator, um sicherzustellen, dass wir in einem Block sind ein einziges Mal.

Live demo

+0

Faule quantifiers nicht genug sind, um die regex zu halten von „Ende der Transaktion“ Grenzen überqueren: https://regex101.com/r/mU4vW8/2 –

+0

@TimPietzcker Das ist, weil Sie mit ' g' Modifizierer, der seinen besten Job machen muss. – revo

+0

Nein. Der 'g' Modifikator bedeutet" Finden Sie alle Übereinstimmungen statt nur die erste ". –

Verwandte Themen