浮点数的正则表达式

时间:2012-09-28 15:32:07

标签: regex

我有一个匹配浮点数的任务。我为它编写了以下正则表达式:

[-+]?[0-9]*\.?[0-9]*

但是,它会返回错误:

Invalid escape sequence (valid ones are  \b  \t  \n  \f  \r  \"  \'  \\ )

据我所知,我们还需要为.使用转义字符。请纠正我错在哪里。

14 个答案:

答案 0 :(得分:186)

TL; DR

使用[.]代替\.[0-9]代替\d,以避免在某些语言(例如Java)中转义问题。

感谢the nameless one最初认识到这一点。 功能

匹配浮点数的一个相对简单的模式是

[+-]?([0-9]*[.])?[0-9]+

这将匹配:

  • 123
  • 123.456
  • .456

查看working example

如果您还想匹配123.(没有小数部分的句号),那么您需要稍微长一点的表达式:

[+-]?([0-9]+([.][0-9]*)?|[.][0-9]+)

有关此模式的更全面解释,请参阅pkeller's answer

如果要包含非十进制数字,例如十六进制和八进制,请参阅我对How do I identify if a string is a number?的回答。

如果您想验证输入是一个数字(而不是在输入中找到一个数字),那么您应该使用^$包围该模式,像这样:

^[+-]?([0-9]+([.][0-9]*)?|[.][0-9]+)$

不规则正则表达式

"正则表达式",在大多数现代语言,API,框架,库等中实现,都基于formal language theory中开发的概念。但是,软件工程师添加了许多扩展,使这些实现远远超出了正式定义。因此,虽然大多数正则表达式引擎彼此相似,但实际上并没有标准。因此,很大程度上取决于您使用的语言,API,框架或库。

(顺便说一下,为了帮助减少混淆,许多人已经开始使用" 正则表达式"或" 正则表达式"来描述这些增强的匹配语言。有关详细信息,请参阅RexEgg.com上的Is a Regex the Same as a Regular Expression?。)

也就是说,大多数正则表达式引擎(实际上,据我所知,所有这些引擎都会接受\.。最有可能的是逃避问题。

逃脱的麻烦

某些语言内置了对正则表达式such as JavaScript的支持。对于那些不合适的语言,逃避可能是个问题。

这是因为您基本上使用语言编写语言。例如,Java使用\作为其字符串中的转义字符,因此如果要在字符串中放置文字反斜杠字符,则必须将其转义:

// creates a single character string: "\"
String x = "\\";

但是,正则表达式使用\字符进行转义,因此如果要匹配文字\字符,则必须为正则表达式引擎转义它,并且然后再次为Java逃脱:

// Creates a two-character string: "\\"
// When used as a regex pattern, will match a single character: "\"
String regexPattern = "\\\\";

在您的情况下,您可能没有使用您编程的语言中的反斜杠字符进行转义:

// will most likely result in an "Illegal escape character" error
String wrongPattern = "\.";
// will result in the string "\."
String correctPattern = "\\.";

所有这些逃脱都会让人感到非常困惑。如果您使用的语言支持raw strings,那么您应该使用这些来减少反斜杠的数量,但并非所有语言都这样做(最值得注意的是:Java)。幸运的是,有一种替代方案可以在某些时候起作用:

String correctPattern = "[.]";

对于正则表达式引擎,\.[.]的含义完全相同。请注意,这并不适用于所有情况,例如换行符(\\n),方括号(\\[)和反斜杠(\\\\[\\])。< / p>

关于匹配数字的说明

(提示:这比你想象的更难)

匹配一个数字是你认为用正则表达式很容易的事情之一,但它实际上相当棘手。让我们一块一块地看看你的方法:

[-+]?

匹配可选的-+

[0-9]*

匹配0个或更多个连续数字

\.?

匹配可选的.

[0-9]*

匹配0个或更多个连续数字

首先,我们可以通过对数字使用character class shorthand来清理这个表达式(注意这也容易受到上面提到的转义问题的影响):

[0-9] = \d

我将在下方使用\d,但请记住,它与[0-9]的含义相同。 (嗯,实际上,在某些引擎中\d会匹配所有脚本中的数字,因此它匹配的数量超过[0-9],但在您的情况下这可能并不重要。)

现在,如果仔细观察,您会发现模式的每个部分都是可选的。此模式可以匹配0长度的字符串;仅由+-组成的字符串;或者,仅由.组成的字符串。这可能不是你想要的。

为了解决这个问题,从#34;锚定&#34;开始是有帮助的。你的正则表达式是最小的必需字符串,可能是一个数字:

\d+

现在我们要添加小数部分,但它并没有达到您认为可能的位置:

\d+\.?\d* /* This isn't quite correct. */

这仍然会匹配123.之类的值。更糟糕的是,它有一个tinge of evil。期间是可选的,这意味着您已经并排了两个重复的课程(\d+\d*)。如果以错误的方式使用,将系统打开到DoS攻击,这实际上可能是危险的。

要解决这个问题,我们需要根据需要对句子进行处理(以分隔重复的字符类),而不是将句点视为可选项,而是将整个小数部分设为可选:

\d+(\.\d+)? /* Better. But... */

现在看起来好多了。我们需要在第一个数字序列和第二个数字序列之间有一段时间,但这是一个致命的缺陷:我们无法匹配.123,因为现在需要一个前导数字。

这实际上非常容易修复。而不是制作&#34;十进制&#34;数字部分可选,我们需要将其视为一系列字符:1个或多个可以加.为前缀的数字,可以加上0或更多数字作为前缀:

(\d*\.)?\d+

现在我们只需添加标志:

[+-]?(\d*\.)?\d+

当然,这些斜杠在Java中非常烦人,所以我们可以替换我们的长形字符类:

[+-]?([0-9]*[.])?[0-9]+

匹配与验证

这在评论中出现过几次,所以我在补充和验证方面添加了一个附录。

匹配的目标是在输入中找到一些内容(&#34;大海捞针&#34;)。 验证的目标是确保输入采用预期的格式。

正则表达式本质上只有匹配文本。给定一些输入,他们会找到一些匹配的文本,或者他们不会。然而,通过&#34; snpping&#34;使用锚标记(^$)对输入的开头和结尾的表达式,我们可以确保找不到匹配,除非整个输入与表达式匹配,有效地使用正则表达式验证

上述正则表达式([+-]?([0-9]*[.])?[0-9]+)将匹配目标字符串中的一个或多个数字。所以给出了输入:

apple 1.34 pear 7.98 version 1.2.3.4

正则表达式将匹配1.347.981.2.3.4

要验证给定输入是一个数字而不是数字,&#34; snap&#34;通过将其包装在锚标记中来表达输入的开头和结尾:

^[+-]?([0-9]*[.])?[0-9]+$

如果整个输入是浮点数,则只会找到匹配项,如果输入包含其他字符,则不会找到匹配项。因此,如果输入1.2,则会找到匹配项,但在apple 1.2 pear处找不到匹配项。

请注意,某些正则表达式引擎具有validateisMatch或类似功能,它基本上会执行我自动描述的内容,如果匹配则返回true如果找不到匹配项,则找到并false。还要记住,某些引擎允许您设置标志,这些标志会更改^$的定义,匹配行的开头/结尾而不是整个输入的开头/结尾。这通常不是默认值,而是要注意这些标志。

答案 1 :(得分:17)

我认为在撰写本文时,本页面上的任何答案都是正确的(在其他地方也有很多其他建议也是错误的)。复杂的是你必须匹配以下所有可能性:

  • 无小数点(即整数值)
  • 小数点前后的数字(例如0.3522.165
  • 仅限小数点前的数字(例如0.1234.
  • 仅限小数点后的数字(例如.0.5678

同时,您必须确保某处至少有一位数字,即不允许以下数字:

  • 自己的小数点
  • 没有数字的有符号小数点(例如+.-.
  • +-自己
  • 一个空字符串

这一开始看起来很棘手,但找到灵感的一种方法是查看java.lang.Double.valueOf(String)方法的OpenJDK来源(从http://hg.openjdk.java.net/jdk8/jdk8/jdk开始,点击&#34;浏览&#34;,导航向下/src/share/classes/java/lang/并找到Double类。这个类包含的长正则表达式可以满足OP可能没有想到的各种可能性,但是为了简单起见忽略了处理NaN,无穷大,十六进制表示法和指数的部分,以及使用{{1}而不是单个数字的POSIX表示法,我可以减少正则表达式的重要部分,对于没有指数的有符号浮点数:

\d

我不认为有一种方法可以避免[+-]?((\d+\.?\d*)|(\.\d+))构造而不允许任何不包含数字的内容,或者禁止在小数点之前没有数字或者之后没有数字的可能性之一它

显然,在实践中,你需要在正则表达式本身或使用它的代码中处理尾随或前面的空格。

答案 2 :(得分:7)

你需要的是:

[\-\+]?[0-9]*(\.[0-9]+)?

我逃脱了&#34; +&#34;和&#34; - &#34;标志,并将小数与其后面的数字分组,因为类似&#34; 1。&#34;不是有效的数字。

更改将允许您匹配整数和浮点数。例如:

0
+1
-2.0
2.23442

答案 3 :(得分:3)

这很简单:你使用过Java,你应该使用\\.而不是\.(在Java中搜索字符转义)。

答案 4 :(得分:2)

这个对我有用:

(?P<value>[-+]*\d+\.\d+|[-+]*\d+)

你也可以使用这个(没有命名参数):

([-+]*\d+\.\d+|[-+]*\d+)

使用一些在线正则表达式测试程序进行测试(例如regex101)

答案 5 :(得分:0)

[+-]?(([1-9][0-9]*)|(0))([.,][0-9]+)?

[+-]? - 可选的主要标志

(([1-9][0-9]*)|(0)) - 不带前导零的整数,包括单个零

([.,][0-9]+)? - 可选的小数部分

答案 6 :(得分:0)

^[+]?([0-9]{1,2})*[.,]([0-9]{1,1})?$

这将匹配:

  1. 1.2
  2. 12.3
  3. 1,2
  4. 12,3

答案 7 :(得分:0)

我想匹配大多数语言认为有效的数字(整数和浮点数):

  • '5' / '-5'

  • '1.0' / '1.' / '.1' / '-1.' / '-.1'

  • '0.45326e+04', '666999e-05', '0.2e-3', '-33.e-1'

注意:

  • 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

为了同时支持“ 1”。和'.1',我们需要一个OR运算符('|'),以确保排除'。'。匹配。

[+-]? +/-是可选的,因为?表示0或1个匹配项

(因为我们有2个子表达式,我们需要将它们放在括号中

\d+([.]\d*)?(e[+-]?\d+)?用于数字开头的数字

|分隔子表达式

[.]\d+(e[+-]?\d+)?这是针对以'。'开头的数字。

)表达式的结尾

  • 对于以'。'开头的数字

[.]第一个字符是点(在方括号内,否则是通配符)

\d+一个或多个数字

(e[+-]?\d+)?这是一个可选的科学计数法(由于以“?”结尾,匹配项为0或1)

  • 对于以数字开头的数字

\d+一个或多个数字

([.]\d*)?可选地,我们可以在其后有一个零位或多个数字的点字符

(e[+-]?\d+)?这是一个可选的科学记号

  • 科学计数法

e指定指数的文字

[+-]?可选指数

\d+一个或多个数字

所有这些组合:

[+-]?(\d+([.]\d*)?(e[+-]?\d+)?|[.]\d+(e[+-]?\d+)?)

答案 8 :(得分:0)

在C ++中使用正则表达式库

答案会像这样:

[0-9]?([0-9]*[.])?[0-9]+

请注意,我不带符号符号,如果您希望将其与符号符号一起使用,它将解决此问题:

[+-]?([0-9]*[.])?[0-9]+

这也分隔了常规数字或十进制数字。

答案 9 :(得分:0)

用符号表示时,浮点数可以按以下形状出现:

  1. 123
  2. 123。
  3. 123.24
  4. .24
  5. 2e-2 = 2 * 10战俘-2 = 2 * 0.1
  6. 4E + 4 = 4 * 10战俘4 = 4 * 10000

对于创建float常规表达式,我将首先创建“ int常规表达式变量”:

(([1-9][0-9]*)|0) will be int

现在,我将写一些小块的float常规表达式-解决方案是用或simbol“ |”合并这些块。

大块:

- (([+-]?{int}) satysfies case 1
- (([+-]?{int})"."[0-9]*)  satysfies cases 2 and 3
- ("."[0-9]*) satysfies case 4
- ([+-]?{int}[eE][+-]?{int}) satysfies cases 5 and 6

最终解决方案(包含小块):

(([+-]?{int})|(([+-]?{int})"."[0-9]*)|("."[0-9]*)|([+-]?{int}[eE][+-]?{int})

答案 10 :(得分:0)

对于那些搜索将验证一个整个输入的正则表达式的人来说,该输入应该是一个带符号浮点点数 用户输入的字符。

即首先是一个符号(应该匹配并有效),然后是所有数字(仍然匹配和有效)及其可选的小数部分。

在 JS 中,我们使用 onkeydown/oninput 事件+以下正则表达式:

^[+-]?[0-9]*([\.][0-9]*)?$

答案 11 :(得分:0)

这会捕获 C/C++ 代码中识别的浮点数:

[+-]?((((\d+\.?\d*)|(\.\d+))([eE][+-]?\d+[fF]?)?)|((\d+\.\d*)|(\.\d+))[fF]?)
  • +/- 符号
  • 只有digits、digits.、.digits或digits.digits
  • 带有 e 或 E、+/- 符号和数字的可选指数
  • 末尾可选 f 或 F,但前提是数字包含 .或指数

答案 12 :(得分:-1)

[+/-] [0-9]*.[0-9]+

尝试此解决方案。

答案 13 :(得分:-1)

for javascript

const test = new RegExp('^[+]?([0-9]{0,})*[.]?([0-9]{0,2})?$','g');

哪个适合 1.23 1234.22 0 0.12 12

您可以更改{}中的部分,以获得十进制长度和小数前面的不同结果。这用于输入输入数字和检查每个输入,因为您只键入允许传递的内容。