Expressão regular de número decimal, em que dígito após decimal é opcional

112

Preciso de uma expressão regular que valide um número, mas não exija um dígito após o decimal. ie.

123
123.
123.4

tudo seria válido

123..

seria inválido

Qualquer um seria muito apreciado!

Trish
fonte
A melhor resposta está aqui: stackoverflow.com/a/39399503/715269
Gangnus

Respostas:

190

Use o seguinte:

/^\d*\.?\d*$/
  • ^ - Início da linha;
  • \d* - 0 ou mais dígitos;
  • \.?- Um ponto opcional (com escape, porque no regex, .é um caractere especial);
  • \d* - 0 ou mais dígitos (a parte decimal);
  • $ - Fim da linha.

Isso permite 0,5 decimal em vez de exigir o zero à esquerda, como 0,5

João silva
fonte
2
@OrangeDog, seu original combina mais do que você deseja. por exemplo, 'cow3.45tornado';)
S. Albano
39
Também corresponde a um único ponto que não é um número decimal válido. Um regex melhor seria o /^\d*\.?\d+$/que forçaria um dígito após um ponto decimal.
Chandranshu
2
@Chandranshu e corresponde a uma string vazia, que sua alteração também resolveria.
OGHaza
2
@Chandranshu "não requer um dígito após o decimal"
OrangeDog
3
Esta solução não funciona. Requer decimais enquanto OP diz claramente: decimais opcionais.
Alex G
113
/\d+\.?\d*/

Um ou mais dígitos ( \d+), ponto opcional ( \.?), zero ou mais dígitos ( \d*).

Dependendo do seu uso ou mecanismo de regex, pode ser necessário adicionar âncoras de linha de início / fim:

/^\d+\.?\d*$/

Visualização de expressão regular

Demonstração Debuggex

OrangeDog
fonte
12
Sim, mas a resposta mais votada está errada, corresponde a ambas .e à string vazia.
OrangeDog
1
@Gangnus Nem diz que ".digit" deve ser correspondido. Se eles queriam isso, deveriam ter dito.
OrangeDog
2
@EqualityInTech Tenho certeza que não - não tem nenhum agrupamento.
OrangeDog
1
Hmm ... Acho que posso não entender totalmente as expressões regulares malignas como pensei que entendia. Desculpe.
JDB ainda se lembra de Monica
1
@AlexanderRyanBaggett corresponde exatamente ao que a pergunta especificou. Como você pode ver, não inclui -nada.
OrangeDog
74

Você precisa de uma expressão regular como a seguinte para fazer isso corretamente:

/^[+-]?((\d+(\.\d*)?)|(\.\d+))$/

A mesma expressão com espaço em branco, usando o modificador estendido (conforme suportado por Perl):

/^  [+-]? ( (\d+ (\.\d*)?)  |  (\.\d+) ) $/x

ou com comentários:

/^           # Beginning of string
 [+-]?       # Optional plus or minus character
 (           # Followed by either:
   (           #   Start of first option
     \d+       #   One or more digits
     (\.\d*)?  #   Optionally followed by: one decimal point and zero or more digits
   )           #   End of first option
   |           # or
   (\.\d+)     #   One decimal point followed by one or more digits
 )           # End of grouping of the OR options
 $           # End of string (i.e. no extra characters remaining)
 /x          # Extended modifier (allows whitespace & comments in regular expression)

Por exemplo, ele corresponderá a:

  • 123
  • 23,45
  • 34
  • 0,45
  • -123
  • -273,15
  • -42.
  • -,45
  • +516
  • +9,8
  • +2.
  • +.5

E rejeitará esses não-números:

  • . (ponto decimal único)
  • -. (ponto decimal negativo)
  • +. (mais o ponto decimal)
  • (string vazia)

As soluções mais simples podem rejeitar incorretamente números válidos ou combinar esses não-números.

Hoylen
fonte
1
Melhor porque corresponde a um número seguido por um ponto (42.). No entanto, há um bug / falso positivo, pois corresponde a este: 3 .... 3 que pode ser corrigido adicionando mais dois parênteses para impor ^ $ caracteres iniciais e finais: / ^ ([+ -]? (\ D + (\ . \ d *)?) | (\. \ d +)) $ /
Pete Alvin
1
Obrigado Pete, bem localizado. A resposta agora foi corrigida, adicionando parênteses extras para que se comporte como planejado. Agora está escrito como ^A?(B|C)$. Anteriormente, era escrito como o ^A?B|C$que realmente significa (^A?B)|(C$)que estava incorreto. Nota: ^(A?B|C)$também está incorreto, porque na verdade significa ^((A?B)|(C))$que não corresponderia a "+.5".
Hoylen
2
Esta é a melhor resposta. As outras respostas não tratam de todos os casos. Eu mesmo faço algo semelhante, exceto que uso uma antecipação para lidar com os casos de dígitos ausentes: /^[+-]?(?=\d|\.\d)\d*(\.\d*)?$ /
PhilHarvey
1
Essa é a única regex correta aqui. Mas algumas pessoas discordam de "34.". Eu proporia + após o segundo d em vez de *
Gangnus
1
Isso também corresponde a 0000.2, o que provavelmente não é o desejado.
Aaron Zorel
11

Experimente este regex:

\d+\.?\d*

\ d + dígitos antes do decimal opcional
.? decimal opcional (opcional devido ao? quantificador)
\ d * dígitos opcionais após decimal

Kash
fonte
1
Não, esse não corresponde123.
Bart Kiers
1
Obrigado pela nota. Modificou meu regex.
Kash
4
Na verdade, mas agora você acabou de editá-lo no que já foi postado por outra pessoa. Considere apenas remover mais uma resposta "correta".
Bart Kiers
10

Acho que este é o melhor porque atende a todos os requisitos:

^\d+(\\.\d+)?$
Luca Manzo
fonte
1
Para mim esta é a melhor resposta, já que a string: "4". (por exemplo) não é um número válido, pelo menos na linguagem ruby. No entanto, as respostas mais votadas aceitam "4". como um número regex, o que está errado.
Victor
3

Acabei usando o seguinte:

^\d*\.?\d+$

Isso torna o seguinte inválido:

.
3.
Charles Naccio
fonte
Você pode precisar de barras dependendo do idioma que está usando. Por exemplo: /^\d*\.?\d+$/
Charles Naccio
isso permitirá.3
Royi Namir,
3

você pode usar isto:

^\d+(\.\d)?\d*$

correspondências:
11
11,1
0,2

não corresponde:
.2
2.
2.6.9

Ahmed Abdulkafy
fonte
Obrigado, muito simples e corresponde ao que eu preciso
Hany
2

Que lingua? No estilo Perl:^\d+(\.\d*)?$

Luis
fonte
2

Isso é o que eu fiz. É mais estrito do que qualquer um dos anteriores (e mais correto do que alguns):

^0$|^[1-9]\d*$|^\.\d+$|^0\.\d*$|^[1-9]\d*\.\d*$

Strings que passam:

0
0.
1
123
123.
123.4
.0
.0123
.123
0.123
1.234
12.34

Strings que falham:

.
00000
01
.0.
..
00.123
02.134
Xiaohang James Miao
fonte
2
^[+-]?(([1-9][0-9]*)?[0-9](\.[0-9]*)?|\.[0-9]+)$

deve refletir o que as pessoas geralmente pensam como um número decimal bem formado.

Os dígitos antes da vírgula decimal podem ser um único dígito, caso em que pode ser de 0 a 9, ou mais de um dígito, caso em que não pode começar com 0.

Se houver algum dígito presente antes do sinal decimal, o decimal e os dígitos seguintes serão opcionais. Caso contrário, um decimal deve estar presente seguido de pelo menos um dígito. Observe que vários zeros finais são permitidos após o ponto decimal.

grep -E '^[+-]?(([1-9][0-9]*)?[0-9](\.[0-9]*)?|\.[0-9]+)$'

corresponde corretamente ao seguinte:

9
0
10
10.
0.
0.0
0.100
0.10
0.01
10.0
10.10
.0
.1
.00
.100
.001

bem como seus equivalentes assinados, ao passo que rejeita o seguinte:

.
00
01
00.0
01.3

e seus equivalentes assinados, bem como a string vazia.

Aaron Zorel
fonte
1
(?<![^d])\d+(?:\.\d+)?(?![^d])

limpo e simples.

Isso usa Sufixo e Prefixo, recursos RegEx.

Ele retorna diretamente verdadeiro - falso para a condição IsMatch

Prashant P
fonte
1
^\d+(()|(\.\d+)?)$

Veio com isso. Permite números inteiros e decimais, mas força um decimal completo (números iniciais e finais) se você decidir inserir um decimal.

cvanniekerk
fonte
1

O que você perguntou já foi respondido, então esta é apenas uma informação adicional para aqueles que querem apenas 2 dígitos decimais se o ponto decimal opcional for inserido:

^\d+(\.\d{2})?$

^: início da string
\ d: um dígito (igual a [0-9])
+: um e vezes ilimitadas

Capturando grupo (. \ D {2})?
? : zero e uma vez. : personagem .
\ d: um dígito (igual a [0-9])
{2}: exatamente 2 vezes
$: fim da string

1: correspondência
123: correspondência
123,00: correspondência
123.: nenhuma correspondência
123 ..: nenhuma correspondência
123,0: nenhuma correspondência
123.000: nenhuma correspondência
123,00,00: nenhuma correspondência

PersyJack
fonte
Isso corresponde a números negativos?
Alexander Ryan Baggett
1
@AlexanderRyanBaggett, você precisa verificar o sinal negativo para que seja: ^ -? \ D + (\. \ D {2})? $
PersyJack
0

Em Perl, use Regexp :: Common, que permitirá que você monte uma expressão regular ajustada para seu formato de número particular. Se você não estiver usando Perl, a expressão regular gerada ainda pode ser usada normalmente por outras linguagens.

Imprimindo o resultado da geração das expressões regulares de exemplo em Regexp :: Common :: Number:

$ perl -MRegexp::Common=number -E 'say $RE{num}{int}'
(?:(?:[-+]?)(?:[0123456789]+))

$ perl -MRegexp::Common=number -E 'say $RE{num}{real}'
(?:(?i)(?:[-+]?)(?:(?=[.]?[0123456789])(?:[0123456789]*)(?:(?:[.])(?:[0123456789]{0,}))?)(?:(?:[E])(?:(?:[-+]?)(?:[0123456789]+))|))

$ perl -MRegexp::Common=number -E 'say $RE{num}{real}{-base=>16}'
(?:(?i)(?:[-+]?)(?:(?=[.]?[0123456789ABCDEF])(?:[0123456789ABCDEF]*)(?:(?:[.])(?:[0123456789ABCDEF]{0,}))?)(?:(?:[G])(?:(?:[-+]?)(?:[0123456789ABCDEF]+))|))
pndc
fonte
0

tente isso. ^[0-9]\d{0,9}(\.\d{1,3})?%?$foi testado e funcionou para mim.

Lawrence Eagles
fonte