TL; DR
Use em [.]vez de \.e em [0-9]vez de \dpara evitar problemas de escape em algumas linguagens (como Java).
Obrigado ao anônimo por originalmente reconhecer isso.
Um padrão relativamente simples para combinar um número de ponto flutuante é
[+-]?([0-9]*[.])?[0-9]+
Isso vai corresponder a:
Veja um exemplo funcional
Se você também quiser fazer a correspondência 123.(um ponto sem parte decimal), precisará de uma expressão um pouco mais longa:
[+-]?([0-9]+([.][0-9]*)?|[.][0-9]+)
Veja a resposta de pkeller para uma explicação mais completa deste padrão
Se você deseja incluir números não decimais, como hexadecimal e octal, consulte minha resposta a Como posso identificar se uma string é um número? .
Se você deseja validar que uma entrada é um número (em vez de encontrar um número na entrada), você deve cercar o padrão com ^e $, assim:
^[+-]?([0-9]+([.][0-9]*)?|[.][0-9]+)$
Expressões regulares irregulares
As "expressões regulares", conforme implementadas na maioria das linguagens modernas, APIs, frameworks, bibliotecas, etc., são baseadas em um conceito desenvolvido na teoria da linguagem formal . No entanto, os engenheiros de software adicionaram muitas extensões que levam essas implementações muito além da definição formal. Portanto, embora a maioria dos mecanismos de expressão regular sejam semelhantes, na verdade não existe um padrão. Por isso, depende muito de qual linguagem, API, framework ou biblioteca você está usando.
(A propósito, para ajudar a reduzir a confusão, muitos passaram a usar " regex " ou " regexp " para descrever essas linguagens de correspondência aprimoradas. Consulte Regex é o mesmo que uma expressão regular? Em RexEgg.com para obter mais informações.)
Dito isso, a maioria dos motores de regex (na verdade, todos eles, pelo que eu sei) aceitariam \.. Provavelmente, há um problema com o escape.
O problema de escapar
Algumas linguagens têm suporte integrado para regexes, como JavaScript . Para aquelas linguagens que não o fazem, o escape pode ser um problema.
Isso ocorre porque você basicamente está codificando em um idioma dentro de outro idioma. Java, por exemplo, usa \como um caractere de escape dentro de suas strings, então se você quiser colocar um caractere literal de barra invertida em uma string, você deve escapar dele:
// creates a single character string: "\"
String x = "\\";
No entanto, regexes também usam o \caractere para escape, portanto, se você quiser corresponder a um \caractere literal , deverá escapar dele para o mecanismo de regexe e, em seguida, escapar novamente para Java:
// Creates a two-character string: "\\"
// When used as a regex pattern, will match a single character: "\"
String regexPattern = "\\\\";
No seu caso, você provavelmente não escapou do caractere de barra invertida na linguagem em que está programando:
// will most likely result in an "Illegal escape character" error
String wrongPattern = "\.";
// will result in the string "\."
String correctPattern = "\\.";
Toda essa fuga pode ser muito confusa. Se a linguagem com a qual você está trabalhando suporta strings brutas , então você deve usá-las para reduzir o número de barras invertidas, mas nem todas as linguagens suportam (mais notavelmente: Java). Felizmente, há uma alternativa que funcionará algumas vezes:
String correctPattern = "[.]";
Para um motor regex, \.e [.]significa exatamente a mesma coisa. Observe que isso não funciona em todos os casos, como nova linha ( \\n), colchete de abertura ( \\[) e barra invertida ( \\\\ou [\\]).
Uma nota sobre números correspondentes
(Dica: é mais difícil do que você pensa)
Combinar um número é uma daquelas coisas que você acha que é muito fácil com regex, mas na verdade é bem complicado. Vamos dar uma olhada em sua abordagem, peça por peça:
[-+]?
Combine um opcional -ou+
[0-9]*
Corresponde a 0 ou mais dígitos sequenciais
\.?
Combine um opcional .
[0-9]*
Corresponde a 0 ou mais dígitos sequenciais
Primeiro, podemos limpar essa expressão um pouco usando uma abreviação de classe de caractere para os dígitos (observe que isso também é suscetível ao problema de escape mencionado acima):
[0-9] = \d
Vou usar \dabaixo, mas lembre-se de que significa a mesma coisa que [0-9]. (Bem, na verdade, em alguns mecanismos \dcorresponderá dígitos de todos os scripts, portanto, corresponderá mais do que [0-9], mas isso provavelmente não é significativo no seu caso.)
Agora, se você observar isso com atenção, perceberá que cada parte do seu padrão é opcional . Esse padrão pode corresponder a uma string de comprimento 0; uma corda composta apenas por +ou -; ou, uma corda composta apenas por a .. Provavelmente não é o que você pretendia.
Para corrigir isso, é útil começar "ancorando" sua regex com a string mínima necessária, provavelmente um único dígito:
\d+
Agora queremos adicionar a parte decimal, mas ela não vai para onde você pensa que poderia:
\d+\.?\d* /* This isn't quite correct. */
Isso ainda corresponderá a valores como 123.. Pior, tem um toque de maldade nisso. O período é opcional, o que significa que você tem duas classes repetidas lado a lado ( \d+e \d*). Na verdade, isso pode ser perigoso se usado da maneira errada, deixando seu sistema vulnerável a ataques DoS.
Para corrigir isso, em vez de tratar o período como opcional, precisamos tratá-lo como obrigatório (para separar as classes de caracteres repetidos) e, em vez disso, tornar opcional toda a parte decimal:
\d+(\.\d+)? /* Better. But... */
Isso está parecendo melhor agora. Exigimos um período entre a primeira sequência de dígitos e a segunda, mas há uma falha fatal: não podemos fazer a correspondência .123porque um dígito inicial agora é necessário.
Na verdade, isso é muito fácil de consertar. Em vez de tornar opcional a parte "decimal" do número, precisamos olhar para ela como uma sequência de caracteres: 1 ou mais números que podem ser prefixados por um .que pode ser prefixado por 0 ou mais números:
(\d*\.)?\d+
Agora apenas adicionamos o sinal:
[+-]?(\d*\.)?\d+
Claro, essas barras são muito irritantes em Java, então podemos substituí-las em nossas classes de caracteres de formato longo:
[+-]?([0-9]*[.])?[0-9]+
Correspondência versus validação
Isso já apareceu nos comentários algumas vezes, então estou adicionando um adendo sobre correspondência versus validação.
O objetivo da correspondência é encontrar algum conteúdo na entrada (a "agulha em um palheiro"). O objetivo da validação é garantir que a entrada esteja em um formato esperado.
Regexes, por sua natureza, só correspondem a texto. Com alguma entrada, eles encontrarão algum texto correspondente ou não. No entanto, ao "encaixar" uma expressão no início e no final da entrada com marcas âncora ( ^e $), podemos garantir que nenhuma correspondência seja encontrada a menos que toda a entrada corresponda à expressão, usando efetivamente regexes para validar .
A regex descrita acima ( [+-]?([0-9]*[.])?[0-9]+) corresponderá a um ou mais números em uma string de destino. Então, dada a entrada:
apple 1.34 pear 7.98 version 1.2.3.4
A regex irá corresponder 1.34, 7.98, 1.2, .3e .4.
Para validar que uma determinada entrada é um número e nada além de um número, "encaixe" a expressão no início e no final da entrada envolvendo-a em tags âncora:
^[+-]?([0-9]*[.])?[0-9]+$
Isso só encontrará uma correspondência se a entrada inteira for um número de ponto flutuante e não encontrará uma correspondência se a entrada contiver caracteres adicionais. Portanto, dada a entrada 1.2, uma correspondência será encontrada, mas apple 1.2 pearnenhuma correspondência será encontrada.
Observe que alguns motores de regex têm uma função validate, isMatchou semelhante, que essencialmente faz o que descrevi automaticamente, retornando truese uma correspondência for encontrada e falsese nenhuma correspondência for encontrada. Também tenha em mente que alguns mecanismos permitem que você defina sinalizadores que alteram a definição de ^e $, correspondendo ao início / fim de uma linha ao invés do início / fim de toda a entrada. Normalmente, esse não é o padrão, mas fique atento a esses sinalizadores.