2016-05-27 19 views
3

Ich habe folgende regexp, die auswertet nie und hängt unendlich:Regexp verursacht unendlich hängen

import java.util.regex.Matcher 
String AUTOGENERATED_HEADER = "#-=-=-= AUTOGENERATED HEADER =-=-=-" 
String AUTOGENERATED_FOOTER = "#-=-=-= AUTOGENERATED FOOTER =-=-=-" 

String messages = '''#-=-=-= AUTOGENERATED HEADER =-=-=- 
a=b 
c=d 
x=y 
#-=-=-= AUTOGENERATED FOOTER =-=-=- 
''' 


Matcher matcher = messages =~ /${AUTOGENERATED_HEADER}[\r\n]+((.*[\r\n]*)*)${AUTOGENERATED_FOOTER}/ 
matcher.find()​ 

Das Problem mit einem Teil ist (.*[\r\n]*). Wenn ich es zu (.*[\r\n]+) ändere, funktioniert es.

Sie können mit Regexp here experimentieren. Kann mir jemand erklären, wie es möglich ist?

+0

Zu einfach zu diagnostizieren: katastrophale Backtracking. Siehe [demo] (https://regex101.com/r/tK7tX5/1) –

Antwort

3

Was Sie hier haben, ist ein Fall von einem katastrophalen Backtracking. Siehe your regex demo. Der Schuldige ist der (.*[\r\n]*)* Teil, der mit anderen Untermustern eingeschlossen ist. Die verschachtelten Quantifizierer verursachen zu viel Rückverfolgung, die Sie auf der Regex-Debugger-Seite bei regex101.com sehen können.

A Lösung ist entweder zu faul Punktanpassung: replace [\r\n]+((.*[\r\n]*)*) mit .*? und füge einen (?s) Modifikator zu Beginn des Musters oder eine abgerollt Version verwenden (die für lange Eingaben viel besser ist, erfordert aber einige Hardcoding).

Siehe (?s)#-=-=-= AUTOGENERATED HEADER =-=-=-.*?#-=-=-= AUTOGENERATED FOOTER =-=-=- in Aktion. Verwenden Sie

Matcher matcher = messages =~ /(?s)${AUTOGENERATED_HEADER}.*?${AUTOGENERATED_FOOTER}/ 
+0

Vielen Dank, dass Sie auf die Option (? S) hingewiesen haben, bei der dot auch mit Newline-Zeichen übereinstimmt. Infolgedessen stellte sich meine Regex als sehr einfach heraus. '(? S) $ {AUTOGENERATED_HEADER} [\ r \ n] + (. *) $ {AUTOGENERATED_FOOTER}' –

+0

Beachten Sie, dass '(. *)' Einen gierigen Quantifizierer enthält und die Regex, die Sie oben angegeben haben, wird vom ersten '$ {AUTOGENERATED_HEADER}' bis zum * letzten * '$ {AUTOGENERATED_FOOTER}' passen. –

Verwandte Themen