2012-04-07 6 views
2

Ich bin ziemlich ok mit grundlegenden reg-ex. aber diese Codezeile, die benutzt wurde, um die tausend Trennung in großen Zahlen zu machen, übersteigt mein Wissen und googelt es ziemlich, hat auch meine Neugier nicht befriedigt. Kann einer von dir bitte eine Minute dauern, um mir die folgende Codezeile zu erklären?Diese Regex-Zeile überschreitet mein Verständnis "(? = (?: D {3}) ++ (?! D))"

someString.replaceAll("(\\G-?\\d{1,3})(?=(?:\\d{3})++(?!\\d))", "$1,"); 

i besonders nicht verstehen, die regex Struktur "(?=(?:\d{3})++(?!\d))".

Vielen Dank im Voraus.

Antwort

3

"(?=(?:\d{3})++(?!\d))" ist ein lookahead assertion.

Es bedeutet "nur Übereinstimmung, wenn gefolgt von ((drei Ziffern, die wir nicht erfassen müssen) ein oder mehrere Male wiederholt (und noch einmal oder mehrmals wiederholt) (nicht gefolgt von einer Ziffer))" . Siehe hierzu explanation über (?:...) Notation. Es heißt nicht-einfangende Gruppe und bedeutet, dass Sie nach dem Match nicht auf diese Gruppe verweisen müssen.

"(\\G-?\\d{1,3})" ist der Teil, der tatsächlich übereinstimmen sollte (aber nur, wenn die oben beschriebenen Bedingungen erfüllt sind).

Edit: Ich denke, + muss ein Sonderzeichen sein, sonst ist es nur ein Plus. Wenn es sich um ein Sonderzeichen handelt (und die Schnellsuche schlägt vor, dass it is in Java, too), ist das zweite redundant.

Edit 2: Dank Alan Moore ist es jetzt klar. Die zweite + bedeutet Possessiv-Matching, also bedeutet es, dass, wenn nach der Prüfung so viele 3-stellige Gruppen wie möglich nicht finden, dass sie nicht von einer Nicht-Ziffer gefolgt sind, die Maschine sofort aufgeben wird, anstatt eine 3 zu treten -digit Gruppe zurück.

+2

Nein, das zweite '+' ist nicht redundant; es macht das erste '+' [Possessiv] (http://www.regular-expressions.info/possessive.html). –

+0

vielen Dank - das hat geholfen! – dotwin

+0

experimentieren mit "++" vs. "+" zeigt keine Auswirkungen auf das Ergebnis, egal was ich hinter meine ganze Zahl (in Java) gesetzt habe. also ich denke, es ist wirklich nur eine Frage der Leistung. – dotwin

3

Dieser Ausdruck hat einige fortgeschrittene Sachen drin. zuerst, die einfachste: \d{3} bedeutet genau drei Ziffern. Das sind deine Tausende.

dann: ++ ist eine Variante von + (was bedeutet, ein oder mehrere), aber besitzergreifend, was bedeutet, dass es alle Tausende essen wird. Ich bin mir nicht ganz sicher, warum das notwendig ist.

?: bedeutet, es ist eine nicht einfangende Gruppe - ich denke, das ist nur aus Leistungsgründen da und konnte weggelassen werden.

ist ein positiver Lookahead - ich denke, das bedeutet, es wird nur geprüft, ob diese Gruppe existiert, aber nicht auf die übereinstimmende Zeichenfolge zählen - was bedeutet, dass sie nicht ersetzt wird.

?! ist ein negativer Look-Ahead - ich nicht ganz verstehen, aber ich glaube, es heißt, es muss NICHT Spiel, was wiederum bedeutet, dass es nicht eine andere Ziffer am Ende der ausgeglichenen Sequenz sein kann. Dies stellt sicher, dass die erste Gruppe die richtigen Ziffern erhält. Z.B. 10000 kann nur als 10 (000) aber nicht als 1 (000) 0 gefunden werden, wenn Sie sehen, was ich meine.

Durch die Lookaheads, wenn ich es richtig verstehe (ich habe es nicht getestet), nur die erste Gruppe würde tatsächlich ersetzt werden, da es das ist, das übereinstimmt.

+0

vielen dank ...! – dotwin

+0

Das Possessiv '++' ist nicht wirklich notwendig. Es macht die Regex etwas effizienter (wie @Lev beobachtet), aber ich bezweifle, dass Sie jemals den Unterschied bemerken würden. Was es ** richtig macht ** ist das '(?! \ D)'. Und die Regex * wird * mehr als einer Gruppe von Ziffern entsprechen; in '12345678' zum Beispiel wird zuerst" 12 ", dann" 345 "angezeigt. –

2

Der interessanteste Teil dieser Regex ist für mich der . Es hat eine Weile gedauert, bis ich mich daran erinnerte, wofür es ist: zu verhindern, dass Kommas zum Bruchteil hinzugefügt werden, wenn es einen gibt.Wenn die Regex einfach waren:

(-?\d{1,3})(?=(?:\d{3})++(?!\d)) 

... diese Zahl:

12345.67890 

... würde am Ende als:

12,345.67,890 

Aber das Hinzufügen \G an den Anfang bedeutet ein Die Übereinstimmung kann nur am Anfang der Zeichenfolge oder an der Position beginnen, an der das vorherige Spiel endete. Es passt also nicht 345 wegen der . folgende, und es passt nicht 67, weil es einige der Zeichenfolge überspringen müsste, um dies zu tun. Und so gibt es richtig:

12,345.67890 

Ich weiß, dass dies auf die Frage keine Antwort, aber ich dachte, es war eine Erwähnung wert.

Verwandte Themen