2016-01-20 12 views
5

Ich unterstütze diese Java-Anwendung, wo die Entwickler einige Filter basierend auf RegEx implementiert. Um so generisch wie möglich zu sein, kompilieren sie die Muster mit dem MULTILINE-Flag.

Neulich bemerkte ich etwas unerwartetes. In Java stimmt das Muster "^\\s*$" nicht mit dem MULTILINE-Flag "" überein. Es passt ohne diese Flagge.

Pattern pattern = Pattern.compile("^\\s*$", Pattern.MULTILINE); 
Matcher matcher = pattern.matcher(""); 

System.out.println("Multiline: "+matcher.find()); 

pattern = Pattern.compile("^\\s*$"); 
matcher = pattern.matcher(""); 

System.out.println("No-multiline: "+matcher.find()); 

Dies erzeugt die folgende Ausgabe

Multiline: false 
Non-Multiline: true 

Gleiche Ergebnisse können für matches() zu sehen:

System.out.println("Multiline: " + ("".matches("(?m)^\\s*$"))); 
System.out.println("No-multiline: " + ("".matches("^\\s*$"))); 

Ich würde alle Fälle erwarten zu lassen.
In Python ist dies der Fall. Dies:

import re 

print(re.search(r'^\s*$', "", re.MULTILINE)) 
print(re.search(r'^\s*$', "")) 

gibt:

<_sre.SRE_Match object; span=(0, 0), match=''> 
<_sre.SRE_Match object; span=(0, 0), match=''> 

In Perl, in beiden Fällen entsprechen, wie gut und ich glaube, ich erinnere mich, es ist die gleiche für PHP zu sein.

Ich würde wirklich schätzen, wenn jemand die Gründe hinter der Art erklären könnte, wie Java diesen Fall behandelt.

+0

Sie haben Recht. Das kam von mir, wenn ich nach den Unterschieden zwischen match() und find() suche. Das Verhalten ist jedoch in beiden Fällen mit beiden Methoden reproduzierbar. Ich habe meine Frage aktualisiert, um find() in beiden Fällen zu verwenden – shmee

+0

Ich wollte nur [den Link zur IDEONE-Demo] (http://ideone.com/1ZoX3V) teilen, der zeigt, dass das Problem mit 'find()' vorhanden ist, auch. –

+1

[Diese Frage] (http://stackoverflow.com/questions/8896201/regular-expression-doesnt-match-empty-string-in-multiline-mode-java) kann einige Einblicke liefern. – sgbj

Antwort

3

Sie übergeben eine leere Zeichenfolge an den Matcher. Mit Pattern.MULTILINE wird die ^ erwartet zu Beginn der Zeichenfolge übereinstimmen, aber in Java kann es ein bisschen anders sein:

Wenn MULTILINE-Modus aktiviert wird dann ^ Matches zu Beginn des Eingangs und nach jedem Leitungsabschluss außer am Ende des Eingangs.

Da die Zeichenfolge leer ist, ist der Anfang der Eingabe ihr Ende.

Hinweis: Wenn Sie das Kennzeichen standardmäßig, aber in der Tat passieren, möchten Sie Muster an der Anfang einer Zeichenfolge übereinstimmen, können Sie \A statt ^ und \z für das Ende der Zeichenfolge statt $ verwenden, die passt den String Start/Ende sogar mit Pattern.MULTILINE an (und sogar ein leerer String wird den Test \\A\\s*\\z bestehen).

+2

Ich verstand die Dokumente in einer Weise, dass '^' immer am Anfang der Zeichenfolge übereinstimmen würde und dass die Ausnahme gilt, wenn vor dem Anfang einer Zeile, die tatsächlich leer ist, und am Ende der Zeichenfolge ein Zeilenabschlusszeichen steht . Danke für den Tipp, stattdessen "\\ A" und "\\ z" zu verwenden. – shmee

Verwandte Themen