2016-05-10 3 views
0
String str = " foo"; 
System.out.println(str.matches("\\s*foo")); //false 
System.out.println(Arrays.toString(str.getBytes()));//[-30, -128, -123, 102, 111, 111] 

Von oben ist das erste Zeichen nicht space.Verwirrendes Ergebnis von java replaceAll, wenn der Anfang von Zeichenfolge mit Leerzeichen übereinstimmt

String replaceStr = str.replaceAll(".*?([a-z]*)", "$1"); 
System.out.println(replaceStr.equals("foo"));//false 

über den Code kann nicht nur foo bekommen.

replaceStr = str.replaceAll("^.*?([a-z]*)$", "$1"); 
System.out.println(replaceStr.equals("foo"));//true 

warum haben ^ und $, dann nur foo bekommen?

+3

Ich kopiert Ihre Zeichenfolge und das erste Zeichen ist '\ u2005' - * 2005 VIER-PER-EM SPACE *. Es gehört zur '\ p {Zs}' Kategorie. Es scheint, als ob du nur '(? U) \\ s * foo' brauchst. Siehe [diese Demo] (https://ideone.com/URLzgC) –

+0

@ WiktorStribiżew Danke, lassen Sie mich dieses Wissen wissen. – zhuguowei

+0

@ WiktorStribiżew aber woher weißt du '-30, -128, -123' ist' \ u2005' – zhuguowei

Antwort

5

.*? ist nicht gierig — es wird versuchen, so wenig wie möglich zu entsprechen, während immer noch die Gesamtübereinstimmung erfolgreich sein.

Da [a-z]* kann null Buchstaben entsprechen, .*?([a-z]*)kann erfolgreich an Position die leere Zeichenkette übereinstimmen 0. Also das ist, was es tut.

Wenn Sie $ anhängen, erzwingen Sie, dass die Regex bis zum Ende der Zeichenfolge (wenn möglich) verlängert wird, so dass die .*? so weit wie möglich übereinstimmt, um dies zu ermöglichen.

Sie können auch das Gleiche erreichen, indem [a-z]+ statt [a-z]* zu schreiben, denn das ist die .*? zwingen würde, weit genug zu passen [a-z]+ Spiel mindestens einen Buchstaben zu lassen.

Aber der beste Ansatz ist wohl zu schreiben:

replaceStr = str.replaceFirst("^[^a-z]*", ""); 

die auf Ihr Arbeitsbeispiel äquivalent ist, aber viel klarer. ([^a-z] bedeutet "ein beliebiges Zeichen neben a-z".)

Verwandte Themen