Expression régulière pour les nombres à virgule flottante
J'ai une tâche pour correspondre à des nombres à virgule flottante. J'ai écrit l'expression régulière suivante: la
[-+]?[0-9]*\.?[0-9]*
Mais, il renvoie une erreur:
Invalid escape sequence (valid ones are \b \t \n \f \r \" \' \\ )
Selon mes connaissances, nous avons besoin d'utiliser un caractère d'échappement pour les .
aussi. S'il vous plaît corrigez-moi où je me trompe.
- Quelle langue est-ce regex utilisé?
- Pourquoi êtes-vous loin de donner 100 points pour un certain nombre/float regex? Le standard a toujours été
(?:\d+(?:\.\d*)?|\.\d+)
et a été publié à l'infini sur SO... - voir aussi stackoverflow.com/questions/638565/...
Vous devez vous connecter pour publier un commentaire.
TL;DR
Utilisation
[.]
au lieu de\.
et[0-9]
au lieu de\d
pour éviter d'échapper à des problèmes dans certaines langues (comme Java).Grâce à l'inconnu pour à l'origine de reconnaître cela.
Une figure relativement simple pour correspondant un nombre à virgule flottante est
Ce sera un match:
123
123.456
.456
Voir un exemple de travail
Si vous aussi vous voulez faire correspondre
123.
(une période sans partie décimale), puis vous aurez besoin d'un peu plus de l'expression:Voir pkeller réponse pour une explication plus complète de ce modèle
Si vous souhaitez inclure les non-nombres décimaux, comme hexadécimal et octal, voir ma réponse à Comment puis-je déterminer si une chaîne est un nombre?.
Si vous voulez valider qu'une entrée est un nombre (plutôt que de trouver un numéro dans l'entrée), vous devez entourer le modèle avec
^
et$
, comme suit:Irrégulière Expressions Régulières
"Expressions régulières", tel que mis en œuvre dans la plupart des langues modernes, les Api, les cadres, les bibliothèques, etc., sont basées sur un concept développé dans théorie des langages formels. Cependant, les ingénieurs logiciels ont ajouté de nombreuses extensions qui prennent 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 effectivement pas de norme. Pour cette raison, beaucoup dépend de ce langage, de l'API, le cadre ou la bibliothèque que vous utilisez.
(D'ailleurs, pour aider à réduire la confusion, beaucoup ont pris à l'aide de "regex" ou "regexp" pour décrire ces renforcée correspondance des langues. Voir Est une expression régulière de la Même comme une Expression Régulière? à RexEgg.com pour plus d'informations.)
Cela dit, la plupart des regex moteurs (en fait, tous, autant que je sache) accepteraient
\.
. Le plus probable, il y a un problème avec l'échappement.La Difficulté à s'Échapper
Certaines langues ont un support intégré pour les regexes, comme JavaScript. Pour les langues qui ne sont pas, en échappant à peut être un problème.
C'est parce que vous êtes essentiellement de codage dans un langage à l'intérieur d'une langue. Java, par exemple, utilise
\
comme un caractère d'échappement dans ses cordes, donc si vous voulez placer un backslash caractère dans une chaîne, vous devez vous échapper:Cependant, regexes aussi utiliser le
\
de caractère pour s'échapper, donc si vous voulez correspondre à un littéral\
personnage, vous devez vous échapper pour la regexe moteur, et ensuite s'échapper à nouveau pour Java:Dans votre cas, vous avez probablement pas échappé, le caractère barre oblique inverse dans la langue de la programmation dans:
Tout cela s'échapper peut devenir très déroutant. Si la langue que vous travaillez en charge chaînes brutes, alors vous devriez utiliser celles à réduire le nombre de barres obliques inverses, mais pas toutes les langues (notamment Java). Heureusement, il existe une alternative qui fonctionne de temps en temps:
Pour un moteur d'expressions régulières,
\.
et[.]
signifient exactement la même chose. Notez que cela ne fonctionne pas dans tous les cas, comme le retour à la ligne (\\n
), crochet ouvert (\\[
) et la barre oblique inverse (\\\\
ou[\\]
).Une Note sur la Correspondance des Numéros
(Indice: C'est plus difficile que vous le pensez)
Correspondant à un certain nombre est une de ces choses que vous auriez pense que c'est assez facile avec la regex, mais c'est en fait assez difficile. Prenons un oeil à votre approche, pièce par pièce:
Correspondre à une option de
-
ou+
Match 0 séquentielles ou plus chiffres
Correspondre à une option de
.
Match 0 séquentielles ou plus chiffres
Tout d'abord, nous pouvons nettoyer cette expression un peu à l'aide d'un le caractère de classe de la sténographie pour les chiffres (à noter que c'est également sensible à la trajectoire de la question mentionnée ci-dessus):
[0-9]
=\d
Je vais utiliser
\d
ci-dessous, mais gardez à l'esprit qu'il signifie la même chose que[0-9]
. (Eh bien, en fait, dans certains moteurs de\d
va correspondre à des chiffres de tous les scripts, donc ça va correspondre à plus de[0-9]
volonté, mais ce n'est probablement pas important dans votre cas.)Maintenant, si vous regardez attentivement, vous vous rendrez compte que chaque partie de votre modèle est facultatif. Ce modèle peut correspondre à un 0-chaîne de longueur; une chaîne composée uniquement de
+
ou-
; ou, une chaîne composée uniquement d'un.
. Ce n'est probablement pas ce que vous avez prévu.Pour résoudre ce problème, il est utile de commencer par "l'ancrage" de votre regex avec le minimum requis de la chaîne, probablement un seul chiffre:
Maintenant, nous voulons ajouter de la partie décimale, mais il ne veut pas aller là où vous pensez qu'il peut:
Ce sera toujours correspondre à des valeurs comme la
123.
. Pire, il a une teinte de mal à ce sujet. La période est facultative, ce qui signifie que vous avez répété deux classes side-by-side (\d+
et\d*
). Ceci peut être vraiment dangereux si utilisé à peu dans le mauvais sens, l'ouverture de votre système jusqu'à des attaques de DoS.Pour résoudre ce problème, plutôt que de considérer la période comme facultatif, nous avons besoin de la traiter comme nécessaire (pour séparer le caractère répété des classes) et au lieu de faire la totalité de la partie décimale en option:
Cette recherche est de mieux maintenant. Nous avons besoin d'une période comprise entre la première séquence de chiffres et le deuxième, mais il y a un défaut fatal: on ne peut pas correspondre à
.123
parce que l'un des principaux chiffres est maintenant nécessaire.C'est en fait assez facile à corriger. Au lieu de faire de la "virgule" partie du numéro optionnelles, nous devons le regarder comme une séquence de caractères: 1 ou plusieurs numéros qui peuvent être préfixés par un
.
qui peut être précédé d'un 0 ou d'autres numéros:Maintenant, il suffit d'ajouter le signe:
Bien sûr, les barres obliques sont assez ennuyeux en Java, pour que nous puissions utiliser notre formulaire de classes de personnage:
De contrepartie rapport à la Validation
C'est dans les commentaires d'un couple de fois, alors que je suis en ajoutant un additif sur la correspondance rapport de validation.
Le but de correspondant est de trouver un peu de contenu à l'intérieur de l'entrée (le "aiguille dans une botte de foin"). L'objectif de validation est de s'assurer que l'entrée est dans un format attendu.
Regexes, de par leur nature, à seulement match texte. Compte tenu de certaines entrées, ils vont trouver quelques du texte correspondant ou ils ne seront pas. Cependant, par "claquer" une expression pour le 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'ensemble de l'entrée correspond à l'expression, de l'utilisation efficace de regexes à valider.La regex décrites ci-dessus (
[+-]?([0-9]*[.])?[0-9]+
) sera match un ou plusieurs numéros à l'intérieur d'une chaîne de caractères. Donc, compte tenu de l'entrée:La regex va correspondre à
1.34
,7.98
,1.2
,.3
et.4
.Pour valider une entrée donnée est un nombre et de rien, mais un certain nombre, "snap", l'expression " au début et à la fin de l'entrée en l'enveloppant dans d'ancrage tags:
Cela ne pourra trouver un match si l'ensemble de l'entrée est un nombre à virgule flottante, et ne trouveront pas un match si l'entrée contient des caractères supplémentaires. Donc, compte tenu de l'entrée
1.2
, un match qui sera trouvé, mais étant donnéapple 1.2 pear
aucun match ne sera trouvé.Noter que certains regex moteurs ont un
validate
,isMatch
ou fonction similaire, qui consiste essentiellement à ne ce que j'ai décrit automatiquement, de retourtrue
si une correspondance est trouvée etfalse
si aucune correspondance n'est trouvée. Aussi garder à l'esprit que certains moteurs vous permettent de définir des indicateurs qui changent la définition de^
et$
, correspondant au début/à la fin d'une ligne, plutôt qu'au début/à la fin de l'ensemble de l'entrée. Ce n'est généralement pas la valeur par défaut, mais être à l'affût pour ces indicateurs.\d+(\.\d*)?|\.\d+
/[-+]?(\d*[.])?\d+/.test("1.bc") // returns true
1.
matchs. Ajouter^
et$
au début et à la fin de la regex si vous souhaitez associer uniquement si l'ensemble de la saisie des matchs.[-+]?(([0-9]*[.]?[0-9]+([ed][-+]?[0-9]+)?)|(inf)|(nan))
, e/d pour float/double précision float. N'oubliez pas un pli cas drapeau de la regex10.30.90
^
et$
). Toutefois, la période n'est pas dans la répétition de la clause, de sorte qu'il ne peut pas correspondre à plus d'un.
.10.30
et puis90
(si vous utilisez/g
), mais séparément. Si vous souhaitez utiliser cette expression pour valider une entrée donnée est un nombre, alors vous devez envelopper dans des ancres:^[+-](\d*\.)?\d+$
[+-]?([0-9]*[.])?[0-9]+
[+-]?((\d+\.?\d*)|(\.\d+))
. Voir ma réponse ailleurs sur cette page pour le raisonnement[+-]?(?:[0-9]*[.])?[0-9]+
. Ensuite, saisir le nombre entier est trivial.Je ne pense pas que les réponses sur cette page au moment de la rédaction sont corrects (également de nombreuses autres suggestions ailleurs sur sont DONC mal aussi). La complication est que vous devez satisfaire à 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 les éléments suivants ne sont pas autorisés:
+.
ou-.
)+
ou-
sur leur propreCela semble difficile au début, mais une façon de trouver l'inspiration est à chercher dans les OpenJDK source pour la
java.lang.Double.valueOf(String)
méthode (départ à http://hg.openjdk.java.net/jdk8/jdk8/jdk, cliquez sur "parcourir", naviguez vers le bas/src/share/classes/java/lang/
et de trouver laDouble
classe). Le long de la regex que cette classe contient accueille les différentes possibilités que l'OP n'ont probablement pas eu à l'esprit, mais l'ignorer pour des raisons de simplicité les parties qui traitent de NaN, l'infini, la notation Hexadécimale et exposants, et à l'aide de\d
plutôt que la notation POSIX pour un seul chiffre, je peux réduire les parties importantes de la regex signé nombre à virgule flottante avec pas d'exposant à:[+-]?((\d+\.?\d*)|(\.\d+))
Je ne pense pas qu'il y est une façon d'éviter les
(...)|(...)
construction sans permettre quelque chose qui ne contient pas de chiffres, ni l'interdiction de l'une des possibilités qui n'a pas de chiffres avant la virgule ou pas de chiffres après elle.Évidemment, dans la pratique, vous devrez répondre pour la fuite ou le précédant, les espaces, que ce soit dans l'expression rationnelle elle-même ou dans le code qui l'utilise.
123.
, alors oui... la ou le commutateur est la seule solution, comme je l'ai indiqué dans le un commentaire sur mon post original.ce que vous avez besoin est:
J'ai échappé à la "+" et "-" et également regroupés en décimal avec ses chiffres suivants depuis quelque chose comme "1." n'est pas un nombre valide.
Les changements vont vous permettre de match de nombres entiers et décimaux. par exemple:
.1
ne seraient pas autorisés, même si cette contribution est universellement reconnu comme correct.-
et+
, qui ne sont pas des numéros. Regex est délicat! 🙂\.
ne fonctionne pas.C'est simple: vous avez utilisé Java et vous devez utiliser
\\.
au lieu de\.
(recherche de personnages pour s'échapper en Java).Cette une a fonctionné pour moi:
Vous pouvez également l'utiliser (sans paramètre nommé):
Utiliser des regex testeur pour tester (par exemple regex101 )
[+-]?
- facultatif signe de début(([1-9][0-9]*)|(0))
entier sans zéro à gauche, y compris le zéro simple([.,][0-9]+)?
- facultatif partie fractionnaireCe sera un match:
Je veux correspondre à ce que la plupart des langues considérer valide nombres (entiers et les flottants):
'5' /'-5'
'1.0' /'1.' /'.1' /'-1.' /'-.1'
'0.45326e+04', '666999e-05', '0.2e-3', '-33.e-1'
Notes:
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 OU ('|') afin de s'assurer que nous exclure". ' partir de la correspondance.
[+-]?
+/- sing est facultative puisque?
signifie 0 ou 1 correspond à(
puisque nous avons 2 sous-expressions nous devons les mettre entre parenthèses\d+([.]\d*)?(e[+-]?\d+)?
C'est pour les numéros commençant par un chiffre|
sépare les sous-expressions[.]\d+(e[+-]?\d+)?
c'est pour les numéros commençant par un '.')
fin d'expressions[.]
premier caractère est le point (à l'intérieur des crochets ou bien c'est un caractère générique)\d+
un ou plusieurs chiffres(e[+-]?\d+)?
c'est une option (0 ou 1 matches en raison de la fin de '?') la notation scientifique\d+
un ou plusieurs chiffres([.]\d*)?
en option on peut avoir un caractère de point un zéro, un ou plusieurs chiffres après il(e[+-]?\d+)?
c'est une option notation scientifiquee
littérale qui spécifie exposant[+-]?
exposant facultatif signe\d+
un ou plusieurs chiffresTous ceux combiné:
En C++ en utilisant la bibliothèque regex
La réponse serait d'aller quelque chose comme ceci:
Notez que je ne prends pas le symbole, si vous le voulais avec le symbole ce serait aller à ce sujet:
Ce sépare également régulièrement un nombre ou un nombre décimal.
D'essayer cette solution.
pour javascript
Qui pourrait fonctionner pour les
1.23
1234.22
0
0.12
12
Vous pouvez changer les pièces dans le
{}
pour obtenir des résultats différents en décimal longueur et le devant de la virgule ainsi. Il est utilisé dans les entrées pour entrer dans le nombre et la vérification de toutes les entrées que vous tapez permettant seulement ce qui passe.