Ich habe die Aufgabe, Gleitkommazahlen abzugleichen. Ich habe den folgenden regulären Ausdruck dafür geschrieben:
[-+]?[0-9]*\.?[0-9]*
Es wird jedoch ein Fehler zurückgegeben:
Invalid escape sequence (valid ones are \b \t \n \f \r \" \' \\ )
Nach meinem Wissen müssen wir auch für das einen Escape-Charakter verwenden .
. Bitte korrigieren Sie mich, wo ich falsch liege.
(?:\d+(?:\.\d*)?|\.\d+)
und ist immer ad infinitum auf SO ...[-+]?([0-9]*[.])?[0-9]+([eE][-+]?\d+)?
Wenn Sie auch die Exponentialnotation abfangen möchten, z. B. 3.023e-23Antworten:
TL; DR
Verwenden Sie
[.]
anstelle von\.
und[0-9]
anstelle von\d
, um zu vermeiden, dass Probleme in einigen Sprachen (wie Java) vermieden werden.Vielen Dank an den Namenlosen , der dies ursprünglich erkannt hat.
Ein relativ einfaches Muster zum Abgleichen einer Gleitkommazahl ist
Dies wird übereinstimmen:
123
123.456
.456
Siehe ein Arbeitsbeispiel
Wenn Sie auch übereinstimmen möchten
123.
(ein Punkt ohne Dezimalteil), benötigen Sie einen etwas längeren Ausdruck:Siehe pkeller Antwort für eine ausführlichere Erklärung dieses Musters
Wenn Sie nicht dezimale Zahlen wie Hex und Oktal einfügen möchten, lesen Sie meine Antwort auf Wie identifiziere ich, ob eine Zeichenfolge eine Zahl ist? .
Wenn Sie möchten bestätigen , dass eine Eingabe eine Zahl ( und nicht eine Zahl innerhalb des Eingangs zu finden), dann sollten Sie das Muster umgeben mit
^
und$
, etwa so:Unregelmäßige reguläre Ausdrücke
"Reguläre Ausdrücke", wie sie in den meisten modernen Sprachen, APIs, Frameworks, Bibliotheken usw. implementiert sind, basieren auf einem in der formalen Sprachtheorie entwickelten Konzept . Softwareentwickler haben jedoch viele Erweiterungen hinzugefügt, die diese Implementierungen weit über die formale Definition hinausführen. Während sich die meisten Engines für reguläre Ausdrücke ähneln, gibt es eigentlich keinen Standard. Aus diesem Grund hängt vieles davon ab, welche Sprache, API, welches Framework oder welche Bibliothek Sie verwenden.
(Um Verwirrung zu vermeiden , haben viele übrigens " Regex " oder " Regexp " verwendet, um diese erweiterten Übereinstimmungssprachen zu beschreiben. Weitere Informationen finden Sie unter Ist ein Regex mit einem regulären Ausdruck identisch ? Auf RexEgg.com.)
Das heißt, die meisten Regex-Motoren (eigentlich alle, soweit ich weiß) würden akzeptieren
\.
. Höchstwahrscheinlich gibt es ein Problem mit der Flucht.Das Problem mit der Flucht
Einige Sprachen bieten integrierte Unterstützung für reguläre Ausdrücke, z. B. JavaScript . Für diejenigen Sprachen, die dies nicht tun, kann das Entkommen ein Problem sein.
Dies liegt daran, dass Sie grundsätzlich in einer Sprache innerhalb einer Sprache codieren. Java wird beispielsweise
\
als Escape-Zeichen in seinen Zeichenfolgen verwendet. Wenn Sie also ein wörtliches Backslash-Zeichen in eine Zeichenfolge einfügen möchten, müssen Sie es maskieren:Allerdings Regexes auch die Verwendung
\
Charakter zu entkommen, wenn Sie also eine wörtliche übereinstimmen soll\
Charakter, müssen Sie es für die regexe Motor entweichen, und es dann wieder entkommen für Java:In Ihrem Fall sind Sie dem Backslash-Zeichen in der Sprache, in der Sie programmieren, wahrscheinlich nicht entkommen:
All diese Flucht kann sehr verwirrend werden. Wenn die Sprache, mit der Sie arbeiten, unformatierte Zeichenfolgen unterstützt , sollten Sie diese verwenden, um die Anzahl der Backslashes zu verringern, aber nicht alle Sprachen (insbesondere Java). Glücklicherweise gibt es eine Alternative, die manchmal funktioniert:
Für eine Regex-Engine
\.
und[.]
genau das Gleiche bedeuten. Beachten Sie, dass dies nicht in jedem Fall funktioniert, wie z. B. newline (\\n
), offene eckige Klammer (\\[
) und Backslash (\\\\
oder[\\]
).Ein Hinweis zu übereinstimmenden Zahlen
(Hinweis: Es ist schwieriger als Sie denken)
Das Abgleichen einer Zahl ist eines der Dinge, von denen Sie denken, dass sie mit Regex recht einfach sind, aber es ist tatsächlich ziemlich schwierig. Schauen wir uns Stück für Stück Ihren Ansatz an:
Passen Sie eine optionale
-
oder+
Entspricht 0 oder mehr aufeinander folgenden Ziffern
Passen Sie eine optionale
.
Entspricht 0 oder mehr aufeinander folgenden Ziffern
Erstens können wir diesen Ausdruck ein wenig bereinigen, indem wir eine Zeichenklassen-Kurzform für die Ziffern verwenden (beachten Sie, dass dies auch für das oben erwähnte Escape-Problem anfällig ist):
[0-9]
=\d
Ich werde
\d
unten verwenden, aber denken Sie daran, dass es das gleiche bedeutet wie[0-9]
. (Nun, tatsächlich\d
stimmen in einigen Engines die Ziffern aller Skripte überein, sodass mehr als[0-9]
die Ziffern übereinstimmen , aber das ist in Ihrem Fall wahrscheinlich nicht von Bedeutung.)Wenn Sie sich das genau ansehen, werden Sie feststellen, dass jeder einzelne Teil Ihres Musters optional ist . Dieses Muster kann mit einer Zeichenfolge mit einer Länge von 0 übereinstimmen. eine Zeichenfolge, die nur aus
+
oder besteht-
; oder eine Zeichenfolge, die nur aus a besteht.
. Dies ist wahrscheinlich nicht das, was Sie beabsichtigt haben.Um dies zu beheben, ist es hilfreich, zunächst Ihren regulären Ausdruck mit der minimal erforderlichen Zeichenfolge zu "verankern", wahrscheinlich mit einer einzelnen Ziffer:
Jetzt wollen wir den Dezimalteil hinzufügen, aber er geht nicht dahin, wo Sie denken, dass es sein könnte:
Dies entspricht weiterhin Werten wie
123.
. Schlimmer noch, es hat einen Hauch von Bösem . Der Zeitraum ist optional, dh Sie haben zwei wiederholte Klassen nebeneinander (\d+
und\d*
). Dies kann tatsächlich gefährlich sein, wenn es falsch verwendet wird und Ihr System für DoS-Angriffe geöffnet wird.Um dies zu beheben, müssen wir den Punkt nicht als optional behandeln, sondern nach Bedarf behandeln (um die wiederholten Zeichenklassen zu trennen) und stattdessen den gesamten Dezimalteil optional machen:
Das sieht jetzt besser aus. Wir benötigen einen Zeitraum zwischen der ersten und der zweiten Ziffernfolge, aber es gibt einen schwerwiegenden Fehler: Wir können nicht übereinstimmen,
.123
da jetzt eine führende Ziffer erforderlich ist.Dies ist eigentlich ziemlich einfach zu beheben. Anstatt den "dezimalen" Teil der Zahl optional zu machen, müssen wir ihn als eine Folge von Zeichen betrachten: 1 oder mehr Zahlen, denen ein Präfix vorangestellt werden
.
kann, denen 0 oder mehr Zahlen vorangestellt werden können:Jetzt fügen wir einfach das Zeichen hinzu:
Natürlich sind diese Schrägstriche in Java ziemlich ärgerlich, daher können wir sie in unseren Langform-Zeichenklassen ersetzen:
Matching versus Validating
Dies ist in den Kommentaren ein paar Mal aufgetaucht, daher füge ich einen Nachtrag zum Matching versus Validieren hinzu.
Das Ziel des Matchings ist es, einen Inhalt innerhalb der Eingabe zu finden (die "Nadel im Heuhaufen"). Das Ziel der Validierung besteht darin, sicherzustellen, dass die Eingabe in einem erwarteten Format vorliegt.
Regexes stimmen naturgemäß nur mit Text überein . Bei einigen Eingaben finden sie entweder passenden Text oder nicht. Durch "Einrasten" eines Ausdrucks am Anfang und Ende der Eingabe mit Ankertags (
^
und$
) können wir jedoch sicherstellen, dass keine Übereinstimmung gefunden wird, es sei denn, die gesamte Eingabe stimmt mit dem Ausdruck überein, wobei zur Validierung Regexes verwendet werden .Der oben beschriebene reguläre Ausdruck (
[+-]?([0-9]*[.])?[0-9]+
) stimmt mit einer oder mehreren Zahlen innerhalb einer Zielzeichenfolge überein . Also gegeben die Eingabe:Die Regex paßt auf
1.34
,7.98
,1.2
,.3
und.4
.Um zu überprüfen, ob eine bestimmte Eingabe eine Zahl und nichts anderes als eine Zahl ist, "fangen" Sie den Ausdruck am Anfang und Ende der Eingabe, indem Sie ihn in Ankertags einschließen:
Dies findet nur dann eine Übereinstimmung, wenn die gesamte Eingabe eine Gleitkommazahl ist, und findet keine Übereinstimmung, wenn die Eingabe zusätzliche Zeichen enthält. Bei der Eingabe
1.2
wird also eine Übereinstimmung gefunden, es werden jedochapple 1.2 pear
keine Übereinstimmungen gefunden.Beachten Sie, dass einige regex Motoren haben eine
validate
,isMatch
oder eine ähnliche Funktion, die im Wesentlichen das tut , was ich automatisch beschrieben habe, zurückkehrt ,true
wenn eine Übereinstimmung gefunden wird undfalse
wenn keine Übereinstimmung gefunden wird. Beachten Sie auch, dass Sie mit einigen Engines Flags setzen können, die die Definition von^
und ändern und$
mit dem Anfang / Ende einer Zeile und nicht mit dem Anfang / Ende der gesamten Eingabe übereinstimmen. Dies ist normalerweise nicht die Standardeinstellung, aber halten Sie Ausschau nach diesen Flags.quelle
\d+(\.\d*)?|\.\d+
/[-+]?(\d*[.])?\d+/.test("1.bc") // returns true
1.
passt. Fügen Sie^
und$
am Anfang und Ende des regulären Ausdrucks hinzu, wenn Sie nur dann übereinstimmen möchten, wenn die gesamte Eingabe übereinstimmt.[-+]?(([0-9]*[.]?[0-9]+([ed][-+]?[0-9]+)?)|(inf)|(nan))
, e / d für Float / Float mit doppelter Genauigkeit. Vergessen Sie nicht eine Faltschachtel zum RegexIch denke nicht, dass eine der Antworten auf dieser Seite zum Zeitpunkt des Schreibens richtig ist (auch viele andere Vorschläge an anderer Stelle auf SO sind ebenfalls falsch). Die Komplikation besteht darin, dass Sie alle folgenden Möglichkeiten erfüllen müssen:
0.35
,22.165
)0.
,1234.
).0
,.5678
)Gleichzeitig müssen Sie sicherstellen, dass irgendwo mindestens eine Ziffer vorhanden ist, dh Folgendes ist nicht zulässig:
+.
oder-.
)+
oder-
alleineDies scheint zunächst schwierig zu sein, aber eine Möglichkeit, Inspiration zu finden, besteht darin, in der OpenJDK-Quelle nach der
java.lang.Double.valueOf(String)
Methode zu suchen (beginnen Sie unter http://hg.openjdk.java.net/jdk8/jdk8/jdk , klicken Sie auf "Durchsuchen" und navigieren Sie nach unten/src/share/classes/java/lang/
und finde dieDouble
Klasse). Der lange reguläre Ausdruck, den diese Klasse enthält, bietet verschiedene Möglichkeiten, die das OP wahrscheinlich nicht in Betracht gezogen hat, ignoriert jedoch der Einfachheit halber die Teile, die sich mit NaN, Unendlichkeit, hexadezimaler Notation und Exponenten befassen, und verwendet\d
anstelle der POSIX-Notation Mit einer einzelnen Ziffer kann ich die wichtigen Teile der Regex für eine vorzeichenbehaftete Gleitkommazahl ohne Exponenten reduzieren auf:[+-]?((\d+\.?\d*)|(\.\d+))
Ich glaube nicht, dass es eine Möglichkeit gibt, die
(...)|(...)
Konstruktion zu vermeiden, ohne etwas zuzulassen, das keine Ziffern enthält, oder eine der Möglichkeiten zu verbieten, die keine Ziffern vor dem Dezimalpunkt oder keine Ziffern danach haben.In der Praxis müssen Sie natürlich auf nachgestellte oder vorangestellte Leerzeichen achten, entweder im regulären Ausdruck selbst oder im Code, der ihn verwendet.
quelle
123.
, dann ja ... der Schalter oder ist die einzige Lösung, wie ich in einem Kommentar zu meinem ursprünglichen Beitrag hervorgehoben habe.[+-]?((?=\.?\d)\d*\.?\d*)
verwendet werden, um den Wechsel zu vermeiden? Es verwendet einen Lookahead ...Was Sie brauchen ist:
Ich bin dem "+" und "-" Zeichen entkommen und habe die Dezimalstelle mit den folgenden Ziffern gruppiert, da so etwas wie "1". ist keine gültige Nummer.
Mit den Änderungen können Sie Ganzzahlen und Gleitkommazahlen abgleichen. beispielsweise:
quelle
.1
dies nicht zulässig wäre, obwohl eine solche Eingabe allgemein als korrekt anerkannt wird.-
und+
, die keine Zahlen sind. Regex ist schwierig! :)\.
nicht funktioniert.Ich möchte übereinstimmen, was die meisten Sprachen als gültige Zahlen betrachten (Ganzzahl und Gleitkommazahlen):
'5' / '-5'
'1.0' / '1.' / '.1' / '-1.' / '-.1'
'0.45326e+04', '666999e-05', '0.2e-3', '-33.e-1'
Anmerkungen:
preceding sign of number ('-' or '+') is optional
'-1.' and '-.1' are valid but '.' and '-.' are invalid
'.1e3' is valid, but '.e3' and 'e3' are invalid
Um beide '1' zu unterstützen. und '.1' benötigen wir einen ODER-Operator ('|'), um sicherzustellen, dass wir '.' vom Matching.
[+-]?
+/- singen ist optional, da?
0 oder 1 Übereinstimmungen bedeuten(
Da wir 2 Unterausdrücke haben, müssen wir sie in Klammern setzen\d+([.]\d*)?(e[+-]?\d+)?
Dies gilt für Zahlen, die mit einer Ziffer beginnen|
trennt Unterausdrücke[.]\d+(e[+-]?\d+)?
Dies gilt für Zahlen, die mit '.' beginnen.)
Ende der Ausdrücke[.]
Das erste Zeichen ist ein Punkt (in Klammern oder ein Platzhalterzeichen).\d+
eine oder mehrere Ziffern(e[+-]?\d+)?
Dies ist eine optionale wissenschaftliche Notation (0 oder 1 Übereinstimmungen aufgrund der Endung '?')\d+
eine oder mehrere Ziffern([.]\d*)?
Optional können wir ein Punktzeichen mit null oder mehr Ziffern danach haben(e[+-]?\d+)?
Dies ist eine optionale wissenschaftliche Notatione
Literal, das den Exponenten angibt[+-]?
optionales Exponentenzeichen\d+
eine oder mehrere ZiffernAlle zusammen:
Auch zu akzeptieren
E
:( Testfälle )
quelle
Dies ist einfach: Sie haben Java verwendet und sollten
\\.
stattdessen verwenden\.
(Suche nach Zeichen, die in Java entkommen).quelle
Dieser hat für mich gearbeitet:
Sie können auch diesen verwenden (ohne benannten Parameter):
Verwenden Sie zum Testen einen Online-Regex-Tester (z. B. Regex101).
quelle
Dies wird übereinstimmen:
quelle
[+-]?
- optionales Leitzeichen(([1-9][0-9]*)|(0))
- Ganzzahl ohne führende Null, einschließlich einzelner Null([.,][0-9]+)?
- optionaler Bruchteilquelle
In C ++ mit der Regex-Bibliothek
Die Antwort würde so aussehen:
Beachten Sie, dass ich das Zeichensymbol nicht nehme. Wenn Sie es mit dem Zeichensymbol möchten, geht es folgendermaßen vor:
Dies trennt auch eine reguläre Zahl oder eine Dezimalzahl.
quelle
In c-Notation kann die Float-Nummer in folgenden Formen auftreten:
Um einen regulären Float-Ausdruck zu erstellen, erstelle ich zuerst eine "int-reguläre Ausdrucksvariable":
Jetzt werde ich kleine Stücke von Float Regular Expresion schreiben - die Lösung besteht darin, diese Stücke mit "|" zu verknüpfen oder zu simbolen.
Brocken:
Endlösung (kleine Stücke zusammenfassen):
quelle
Versuchen Sie diese Lösung.
quelle
für Javascript
Welches würde für 1.23 1234,22 0 0,12 12 funktionieren
Sie können die Teile in ändern
{}
, um unterschiedliche Ergebnisse in Bezug auf die Dezimallänge und die Vorderseite der Dezimalstelle zu erhalten. Dies wird in Eingaben verwendet, um eine Zahl einzugeben und jede Eingabe zu überprüfen, während Sie nur eingeben, was passiert.quelle