J'ai une tâche pour faire correspondre les nombres à virgule flottante. J'ai écrit l'expression régulière suivante pour cela:
[-+]?[0-9]*\.?[0-9]*
Mais, il renvoie une erreur:
Invalid escape sequence (valid ones are \b \t \n \f \r \" \' \\ )
Selon ma connaissance, nous devons utiliser un caractère d'échappement pour le .
également. Veuillez me corriger là où je me trompe.
(?:\d+(?:\.\d*)?|\.\d+)
et a été publiée à l'infini sur SO ...[-+]?([0-9]*[.])?[0-9]+([eE][-+]?\d+)?
si vous voulez aussi attraper la notation exponentielle, e, g, 3.023e-23Réponses:
TL; DR
Utilisez
[.]
au lieu de\.
et[0-9]
au lieu de\d
pour éviter les problèmes d'échappement dans certains langages (comme Java).Merci à celui sans nom pour avoir reconnu cela à l'origine.
Un modèle relativement simple pour faire correspondre un nombre à virgule flottante est
Cela correspondra:
123
123.456
.456
Voir un exemple de travail
Si vous souhaitez également faire correspondre
123.
(un point sans partie décimale), vous aurez besoin d'une expression légèrement plus longue:Voir la réponse de pkeller pour une explication plus complète de ce modèle
Si vous souhaitez inclure des nombres non décimaux, tels que hexadécimal et octal, consultez ma réponse à Comment puis-je identifier si une chaîne est un nombre? .
Si vous voulez valider qu'une entrée est un nombre (plutôt que de trouver un nombre dans l'entrée), vous devez entourer le motif avec
^
et$
, comme ceci:Expressions régulières irrégulières
Les «expressions régulières», telles qu'implémentées dans la plupart des langages modernes, API, frameworks, bibliothèques, etc., sont basées sur un concept développé dans la théorie formelle du langage . Cependant, les ingénieurs logiciels ont ajouté de nombreuses extensions qui poussent ces implémentations bien au-delà de la définition formelle. Ainsi, alors que la plupart des moteurs d'expressions régulières se ressemblent, il n'y a en fait pas de norme. Pour cette raison, tout dépend du langage, de l'API, du framework ou de la bibliothèque que vous utilisez.
(Incidemment, pour aider à réduire la confusion, beaucoup ont commencé à utiliser « regex » ou « regexp » pour décrire ces langages de correspondance améliorés. Voir Une expression régulière est-elle identique à une expression régulière? Sur RexEgg.com pour plus d'informations.)
Cela dit, la plupart des moteurs de regex (en fait, tous, pour autant que je sache) accepteraient
\.
. Très probablement, il y a un problème avec l'échappement.Le problème de la fuite
Certains langages ont un support intégré pour les expressions régulières, comme JavaScript . Pour les langues qui ne le font pas, s'échapper peut être un problème.
C'est parce que vous codez essentiellement dans une langue au sein d'une langue. Java, par exemple, utilise
\
comme caractère d'échappement dans ses chaînes, donc si vous voulez placer un caractère anti-slash littéral dans une chaîne, vous devez l'échapper:Cependant, les expressions régulières utilisent également le
\
caractère pour s'échapper, donc si vous voulez faire correspondre un\
caractère littéral , vous devez l'échapper pour le moteur d'expression régulière, puis l'échapper à nouveau pour Java:Dans votre cas, vous n'avez probablement pas échappé à la barre oblique inverse dans le langage dans lequel vous programmez:
Toutes ces évasions peuvent devenir très déroutantes. Si le langage avec lequel vous travaillez prend en charge les chaînes brutes , vous devez les utiliser pour réduire le nombre de barres obliques inverses, mais tous les langages ne le font pas (notamment Java). Heureusement, il existe une alternative qui fonctionnera parfois:
Pour un moteur regex,
\.
et cela[.]
signifie exactement la même chose. Notez que cela ne fonctionne pas dans tous les cas, comme newline (\\n
), open square bracket (\\[
) et backslash (\\\\
ou[\\]
).Remarque sur la correspondance des nombres
(Indice: c'est plus difficile que vous ne le pensez)
Faire correspondre un nombre est une de ces choses que vous pensez être assez facile avec regex, mais c'est en fait assez délicat. Jetons un coup d'œil à votre approche, pièce par pièce:
Faites correspondre une option
-
ou+
Correspond à 0 ou plusieurs chiffres séquentiels
Faites correspondre une option
.
Correspond à 0 ou plusieurs chiffres séquentiels
Tout d'abord, nous pouvons nettoyer un peu cette expression en utilisant un raccourci de classe de caractères pour les chiffres (notez que cela est également sensible au problème d'échappement mentionné ci-dessus):
[0-9]
=\d
Je vais utiliser
\d
ci-dessous, mais gardez à l'esprit que cela signifie la même chose que[0-9]
. (Eh bien, en fait, dans certains moteurs\d
, les chiffres de tous les scripts correspondront, donc cela correspondra plus que ce[0-9]
ne sera, mais ce n'est probablement pas significatif dans votre cas.)Maintenant, si vous regardez cela attentivement, vous vous rendrez compte que chaque partie de votre modèle est facultative . Ce modèle peut correspondre à une chaîne de longueur 0; une chaîne composée uniquement de
+
ou-
; ou, une chaîne composée uniquement de a.
. Ce n'est probablement pas ce que vous vouliez.Pour résoudre ce problème, il est utile de commencer par «ancrer» votre expression régulière avec la chaîne requise le plus strict, probablement un seul chiffre:
Maintenant, nous voulons ajouter la partie décimale, mais elle ne va pas là où vous pensez qu'elle pourrait:
Cela correspondra toujours à des valeurs telles que
123.
. Pire encore, il y a une teinte perverse à ce sujet. Le point est facultatif, ce qui signifie que vous avez deux classes répétées côte à côte (\d+
et\d*
). Cela peut en fait être dangereux s'il est utilisé de la mauvaise manière, ouvrant votre système aux attaques DoS.Pour résoudre ce problème, plutôt que de traiter le point comme facultatif, nous devons le traiter comme requis (pour séparer les classes de caractères répétées) et à la place rendre la partie décimale entière facultative:
Cela va mieux maintenant. Nous avons besoin d'un point entre la première séquence de chiffres et la seconde, mais il y a un défaut fatal: nous ne pouvons pas faire correspondre
.123
car un chiffre de tête est maintenant requis.C'est en fait assez facile à résoudre. Au lieu de rendre la partie "décimale" du nombre facultative, nous devons la considérer comme une séquence de caractères: 1 ou plusieurs nombres qui peuvent être préfixés par un
.
qui peuvent être préfixés par 0 ou plusieurs nombres:Maintenant, nous ajoutons simplement le signe:
Bien sûr, ces barres obliques sont assez ennuyeuses en Java, nous pouvons donc les remplacer dans nos classes de caractères de forme longue:
Matching versus validation
Cela a été mentionné dans les commentaires à quelques reprises, alors j'ajoute un addendum sur l'appariement et la validation.
Le but de la correspondance est de trouver du contenu dans l'entrée ("l'aiguille dans une botte de foin"). Le but de la validation est de s'assurer que l'entrée est dans un format attendu.
Les expressions régulières, de par leur nature, ne correspondent qu'à du texte. Compte tenu de certains commentaires, ils trouveront un texte correspondant ou ils ne le trouveront pas. Cependant, en "accrochant" une expression au début et à la fin de l'entrée avec des balises d'ancrage (
^
et$
), nous pouvons nous assurer qu'aucune correspondance n'est trouvée à moins que l'entrée entière ne corresponde à l'expression, en utilisant efficacement des expressions régulières pour valider .Le regex décrit ci-dessus (
[+-]?([0-9]*[.])?[0-9]+
) correspondra à un ou plusieurs nombres dans une chaîne cible. Donc, compte tenu de l'entrée:Le regex correspondra
1.34
,7.98
,1.2
,.3
et.4
.Pour valider qu'une entrée donnée est un nombre et rien d'autre qu'un nombre, «accrochez» l'expression au début et à la fin de l'entrée en l'enveloppant dans des balises d'ancrage:
Cela ne trouvera une correspondance que si l'entrée entière est un nombre à virgule flottante, et ne trouvera pas de correspondance si l'entrée contient des caractères supplémentaires. Donc, étant donné l'entrée
1.2
, une correspondance sera trouvée, maisapple 1.2 pear
aucune correspondance ne sera trouvée.Notez que certains moteurs regex ont une fonction
validate
,isMatch
ou similaire, qui fait essentiellement ce que j'ai décrit automatiquement, retournanttrue
si une correspondance est trouvée etfalse
si aucune correspondance n'est trouvée. Gardez également à l'esprit que certains moteurs vous permettent de définir des indicateurs qui modifient la définition de^
et$
, correspondant au début / à la fin d'une ligne plutôt qu'au début / à la fin de l'entrée entière. Ce n'est généralement pas la valeur par défaut, mais soyez à l'affût de ces drapeaux.la source
\d+(\.\d*)?|\.\d+
/[-+]?(\d*[.])?\d+/.test("1.bc") // returns true
1.
correspond. Ajoutez^
et$
au début et à la fin de l'expression régulière si vous ne voulez faire correspondre que si l'entrée entière correspond.[-+]?(([0-9]*[.]?[0-9]+([ed][-+]?[0-9]+)?)|(inf)|(nan))
e / d pour float / double precision float. N'oubliez pas un drapeau pliant à la regexJe ne pense pas qu'aucune des réponses sur cette page au moment de la rédaction soit correcte (de nombreuses autres suggestions ailleurs sur SO sont également fausses). La complication est que vous devez correspondre à toutes les possibilités suivantes:
0.35
,22.165
)0.
,1234.
).0
,.5678
)Dans le même temps, vous devez vous assurer qu'il y a au moins un chiffre quelque part, c'est-à-dire que les éléments suivants ne sont pas autorisés:
+.
-à- dire ou-.
)+
ou-
seulsCela semble délicat au début, mais une façon de trouver l'inspiration est de regarder la source OpenJDK de la
java.lang.Double.valueOf(String)
méthode (commencer à http://hg.openjdk.java.net/jdk8/jdk8/jdk , cliquer sur "parcourir", naviguer vers le bas/src/share/classes/java/lang/
et trouvez laDouble
classe). Le long regex que cette classe contient répond à diverses possibilités que l'OP n'avait probablement pas à l'esprit, mais en ignorant pour simplifier les parties qui traitent de NaN, l'infini, la notation hexadécimale et les exposants, et en utilisant\d
plutôt que la notation POSIX pour un seul chiffre, je peux réduire les parties importantes de l'expression régulière pour un nombre à virgule flottante signé sans exposant à:[+-]?((\d+\.?\d*)|(\.\d+))
Je ne pense pas qu'il existe un moyen d'éviter la
(...)|(...)
construction sans autoriser quelque chose qui ne contient pas de chiffres, ou d'interdire l'une des possibilités qui n'a pas de chiffres avant la virgule décimale ou pas de chiffres après.De toute évidence, dans la pratique, vous devrez prendre en compte les espaces de fin ou précédents, soit dans l'expression régulière elle-même, soit dans le code qui l'utilise.
la source
123.
, alors oui ... le commutateur ou est la seule solution, comme je l'ai souligné dans un commentaire sur mon message d'origine.[+-]?((?=\.?\d)\d*\.?\d*)
peut-il être utilisé pour éviter l'alternance? It uses a lookahead ...ce dont vous avez besoin est:
J'ai échappé aux signes «+» et «-» et j'ai également regroupé la décimale avec ses chiffres suivants depuis quelque chose comme «1». n'est pas un nombre valide.
Les modifications vous permettront de faire correspondre les entiers et les flottants. par exemple:
la source
.1
ne serait pas autorisée, même si une telle entrée est universellement reconnue comme correcte.-
et+
, qui ne sont pas des nombres. Regex est délicat! :)\.
cela ne fonctionne pas.Je veux faire correspondre ce que la plupart des langues considèrent comme des nombres valides (entiers et flottants):
'5' / '-5'
'1.0' / '1.' / '.1' / '-1.' / '-.1'
'0.45326e+04', '666999e-05', '0.2e-3', '-33.e-1'
Remarques:
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
Afin de soutenir à la fois «1». et '.1' nous avons besoin d'un opérateur OR ('|') pour être sûr d'exclure '.' de l'appariement.
[+-]?
+/- chanter est facultatif car?
signifie 0 ou 1 correspondances(
puisque nous avons 2 sous-expressions, nous devons les mettre entre parenthèses\d+([.]\d*)?(e[+-]?\d+)?
Ceci est pour les nombres commençant par un chiffre|
sépare les sous-expressions[.]\d+(e[+-]?\d+)?
c'est pour les nombres commençant par ".")
fin d'expressions[.]
le premier caractère est un point (entre crochets ou bien c'est un caractère générique)\d+
un ou plusieurs chiffres(e[+-]?\d+)?
il s'agit d'une notation scientifique facultative (0 ou 1 correspond à la fin de '?')\d+
un ou plusieurs chiffres([.]\d*)?
facultativement, nous pouvons avoir un caractère point après zéro ou plusieurs chiffres(e[+-]?\d+)?
ceci est une notation scientifique facultativee
littéral qui spécifie l'exposant[+-]?
signe d'exposant facultatif\d+
un ou plusieurs chiffresTous ces éléments combinés:
A accepter
E
aussi:( Cas de test )
la source
C'est simple: vous avez utilisé Java et vous devriez utiliser à la
\\.
place de\.
(recherche de caractères s'échappant en Java).la source
Celui-ci a fonctionné pour moi:
Vous pouvez également utiliser celui-ci (sans paramètre nommé):
Utilisez un testeur de regex en ligne pour le tester (par exemple, regex101)
la source
Cela correspondra:
la source
[+-]?
- signe de tête facultatif(([1-9][0-9]*)|(0))
- entier sans zéro non significatif, y compris un seul zéro([.,][0-9]+)?
- partie fractionnaire facultativela source
En C ++ en utilisant la bibliothèque regex
La réponse se passerait comme ceci:
Notez que je ne prends pas le symbole du signe, si vous le vouliez avec le symbole du signe, cela se passerait:
Cela sépare également un nombre régulier ou un nombre décimal.
la source
En notation C, le nombre flottant peut se présenter sous les formes suivantes:
Pour créer une expression régulière float, je vais d'abord créer "int regular expresion variable":
Maintenant, j'écrirai de petits morceaux d'expression régulière de float - la solution est de concaténer ces morceaux avec ou simbol "|".
Morceaux:
Solution finale (concanant de petits morceaux):
la source
Essayez cette solution.
la source
pour javascript
Ce qui fonctionnerait pour 1,23 1234,22 0 0,12 12
Vous pouvez modifier les parties dans le
{}
pour obtenir des résultats différents en longueur décimale et devant la décimale également. Ceci est utilisé dans les entrées pour entrer le nombre et vérifier chaque entrée lorsque vous tapez, autorisant uniquement ce qui passe.la source