165

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

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

但是,它返回一个错误:

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

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

4

16 回答 16

359

TL;博士

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

感谢无名者最初认识到这一点。

用于匹配较大字符串中的浮点数的一种相对简单的模式是:

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

这将匹配:

  • 123
  • 123.456
  • .456

查看一个工作示例

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

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

有关此模式的更完整解释,请参见pkeller 的回答

如果您想包含更广泛的数字,包括科学记数法和十六进制和八进制等非十进制数字,请参阅我对如何识别字符串是否为数字的回答?.

如果要验证输入是否为数字(而不是在输入中查找数字),则应使用 and 将模式括起来^$如下所示:

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

不规则正则表达式

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

(顺便说一句,为了帮助减少混淆,许多人已经开始使用“ regex ”或“ regexp ”来描述这些增强的匹配语言。有关更多信息,请参阅 RexEgg.com 上的 Regex 与正则表达式相同吗? )

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

逃跑的麻烦

某些语言具有对正则表达式的内置支持,例如 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 = "\\.";

所有这些转义都会变得非常混乱。如果您使用的语言支持原始字符串,那么您应该使用它们来减少反斜杠的数量,但并非所有语言都支持(最值得注意的是:Java)。幸运的是,有一个替代方案在某些时候会起作用:

String correctPattern = "[.]";

对于正则表达式引擎,\.含义[.]完全相同。请注意,这并非在所有情况下都有效,例如换行符 ( \\n)、左方括号 ( \\[) 和反斜杠 ( \\\\or [\\])。

关于匹配数字的注意事项

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

匹配数字是您认为使用正则表达式很容易的事情之一,但实际上非常棘手。让我们一点一点地看一下您的方法:

[-+]?

匹配一个可选的-+

[0-9]*

匹配 0 个或多个连续数字

\.?

匹配一个可选的.

[0-9]*

匹配 0 个或多个连续数字

首先,我们可以通过对数字使用字符类简写来稍微清理一下这个表达式(请注意,这也容易受到上述转义问题的影响):

[0-9]=\d

我将在\d下面使用,但请记住,它的含义与[0-9]. (好吧,实际上,在某些引擎\d中,会匹配所有脚本中的数字,因此它会匹配得更多[0-9],但这在您的情况下可能并不重要。)

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

要解决此问题,首先使用所需的最少字符串(可能是单个数字)“锚定”您的正则表达式会很有帮助:

\d+

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

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

这仍将匹配诸如123.. 更糟糕的是,它带有一丝邪恶的色彩。句点是可选的,这意味着您有两个并排重复的类 (\d+\d*)。如果以错误的方式使用这实际上可能很危险,从而使您的系统容易受到 DoS 攻击。

为了解决这个问题,我们需要将其视为必需(以分隔重复的字符类)而不是将句点视为可选,而是将整个小数部分设为可选:

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

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

这实际上很容易解决。我们不需要将数字的“小数”部分设为可选,而是将其视为一个字符序列:1 个或多个可能以 a 为前缀的数字,可能.以 0 个或多个数字为前缀:

(\d*\.)?\d+

现在我们只需添加符号:

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

当然,这些斜线在 Java 中很烦人,所以我们可以在我们的长格式字符类中替换:

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

匹配与验证

这已经在评论中出现了几次,所以我添加了一个关于匹配与验证的附录。

匹配的目标是在输入中找到一些内容(“大海捞针”)。验证的目的是确保输入是预期的格式。

就其性质而言,正则表达式仅匹配文本。给定一些输入,他们要么会找到一些匹配的文本,要么不会。^但是,通过使用锚标记(和)将表达式“捕捉”到输入的开头和结尾$,我们可以确保找不到匹配项,除非整个输入都与表达式匹配,从而有效地使用正则表达式来验证

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

apple 1.34 pear 7.98 version 1.2.3.4

正则表达式将匹配1.34, 7.98,1.2和..3.4

要验证给定的输入是一个数字,而只是一个数字,请将表达式“捕捉”到输入的开头和结尾,方法是将其包装在锚标记中:

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

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

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

于 2012-09-28T15:37:00.790 回答
35

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

  • 无小数点(即整数值)
  • 小数点前后的数字(例如0.35, 22.165
  • 仅小数点前的数字(例如0., 1234.
  • 仅小数点后的数字(例如.0, .5678

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

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

起初这似乎很棘手,但找到灵感的一种方法是查看该java.lang.Double.valueOf(String)方法的 OpenJDK 源代码(从http://hg.openjdk.java.net/jdk8/jdk8/jdk开始,单击“浏览”,向下导航/src/share/classes/java/lang/并找到Double班级)。此类包含的长正则表达式满足了 OP 可能没有考虑到的各种可能性,但为简单起见,忽略了它处理 NaN、无穷大、十六进制表示法和指数的部分,并使用\d而不是 POSIX 表示法一个数字,我可以将正则表达式的重要部分减少为没有指数的有符号浮点数:

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

我认为没有一种方法可以避免(...)|(...)构造,而不允许不包含数字的内容,或者禁止小数点前没有数字或小数点后没有数字的可能性之一。

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

于 2017-03-06T15:17:39.490 回答
21

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

  • '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 运算符 ('|') 以确保我们排除 '.' 从匹配。

[+-]?+/- sing 是可选的,因为?意味着 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+)?)

也接受E

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

测试用例

于 2019-04-09T12:04:52.597 回答
8

This is simple: you have used Java and you ought to use \\. instead of \. (search for character escaping in Java).

于 2015-03-27T17:09:21.077 回答
8

你需要的是:

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

我转义了“+”和“-”符号,并将小数与其后面的数字分组,因为类似于“1”。不是有效数字。

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

0
+1
-2.0
2.23442
于 2012-09-28T15:35:50.600 回答
3

这个对我有用:

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

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

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

使用一些在线正则表达式测试器来测试它(例如 regex101 )

于 2015-10-17T13:52:34.910 回答
2
^[+-]?([0-9]{1,})[.,]([0-9]{1,})$

这将匹配:

  1. 1.2
  2. 12.3
  3. 123.4
  4. 1,2
  5. 12,3
  6. 123,4
于 2017-02-24T10:57:51.857 回答
1

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

[+-]?((((\d+\.?\d*)|(\.\d+))([eE][+-]?\d+[fF]?)?)|((\d+\.\d*)|(\.\d+))[fF]?)
  • +/- 符号
  • 只有数字、数字、.digits 或digits.digits
  • 带 e 或 E、+/- 符号和数字的可选指数
  • 可选 f 或 F 结尾,但前提是数字包含 a 。或指数
于 2021-04-08T06:03:35.773 回答
1
(\d*)(\.)*(\d+)

这将解析以下内容。

11.00
12
.0

必须有一个数字。小数点和小数点前的数字是可选的。

于 2021-09-19T00:59:41.273 回答
1

对于 javascript

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

这适用于 1.23 1234.22 0 0.12 12

您可以更改 中的部分{}以获得小数长度和小数前面的不同结果。这在输入中用于输入数字并在您键入时检查每个输入,仅允许通过的内容。

于 2018-02-01T20:10:26.550 回答
0
[+/-] [0-9]*.[0-9]+

试试这个解决方案。

于 2016-10-31T13:05:36.353 回答
0

在 C 语言中,答案是这样的:

[+-]?((\d+\.?\d*)|(\.\d+))(([eE][+-]?)?\d+)?[fFlL]?
于 2021-11-07T17:28:32.997 回答
0

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

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

在 JS 中,我们使用onkeydown/oninput事件来做到这一点 + 以下正则表达式:

^[+-]?[0-9]*([\.][0-9]*)?$
于 2021-01-14T10:54:11.603 回答
0
[+-]?(([1-9][0-9]*)|(0))([.,][0-9]+)?

[+-]?- 可选的领先标志

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

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

于 2015-11-11T10:22:09.640 回答
0

在 c 表示法中,浮点数可以以下列形式出现:

  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 * 10 000

为了创建浮点正则表达式,我将首先创建“int 正则表达式变量”:

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

现在,我将编写小块浮点正则表达式 - 解决方案是用符号“|”连接这些块。

块:

- (([+-]?{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})
于 2020-03-09T22:00:16.057 回答
0

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

答案是这样的:

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

请注意,我不使用符号符号,如果您想要它带有符号符号,它会这样做:

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

这也将常规数字或十进制数字分开。

于 2019-05-19T02:34:00.267 回答