浮点数的正则表达式

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

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

但是,它返回一个错误:

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

据我所知,我们还需要为 .使用一个转义字符。请纠正我的错误。

326849 次浏览

你需要的是:

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

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

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

0
+1
-2.0
2.23442

DR

使用 [.]而不是 \.[0-9]而不是 \d,以避免在某些语言(如 Java)中出现转义问题。

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

对于 匹配来说,一个较大字符串中的浮点数相对简单的模式是:

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

这将与:

  • 123
  • 123.456
  • .456

工作范例

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

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

有关此模式的更详细解释,请参见 Pkeller 的回答

如果你想包括更广泛的数字范围,包括科学记数法和非十六进制数字,比如十六进制和八进制,请看我对 如何识别字符串是否为数字?的回答。

如果您希望 确认中的输入是一个数字(而不是在输入中找到一个数字) ,那么您应该用 ^$围绕模式,如下所示:

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

不规则 正则表达式

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

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

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

逃跑的烦恼

有些语言内置了对正则表达式 例如 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)、开方括号(\\[)和反斜杠(\\\\[\\])。

关于匹配数的一个注记

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

匹配一个数字是你认为使用 regex 非常简单的事情之一,但实际上它非常棘手。让我们一点一点看看你的方法:

[-+]?

匹配一个可选的 -+

[0-9]*

匹配0个或多个连续数字

\.?

匹配一个可选的 .

[0-9]*

匹配0个或多个连续数字

First, we can clean up this expression a bit by using a 字符类速记法字符类速记法 for the digits (note that this is also susceptible to the escaping issue mentioned above):

[0-9] = \d

我将在下面使用 \d,但请记住,它的意思与 [0-9]相同。(实际上,在某些引擎中,\d会匹配来自所有脚本的数字,所以它会比 [0-9]匹配得更多,但是在您的情况下,这可能并不重要。)

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

为了解决这个问题,最好从“锚定”你的正则表达式开始,使用最少的字符串,可能是一个数字:

\d+

现在我们要加上小数部分,但它不会到你想的地方:

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

这将仍然匹配像 123.这样的值。更糟糕的是,它有一个 邪恶的气息。句点是可选的,这意味着您有两个并排重复的类(\d+\d*)。如果使用方式不当,这实际上可能会很危险,使您的系统容易受到 DoS 攻击。

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

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

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

这其实很容易解决。与其让数字的“十进制”部分成为可选的,我们需要把它看作一个字符序列: 1个或多个数字前面可能有一个 .,前面可能有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.347.981.2.3.4

为了验证给定的输入是一个数字而不是其他任何东西,可以通过将表达式包装在锚标记中将其“捕获”到输入的开始和结束:

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

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

注意,一些正则表达式引擎有一个 validateisMatch或类似的函数,它实际上执行我所描述的自动操作,如果找到匹配,返回 true,如果没有找到匹配,返回 false。还要记住,有些引擎允许您设置改变 ^$定义的标志,匹配一行的开始/结束,而不是整个输入的开始/结束。这通常不是默认值,但要注意这些标志。

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

这个对我很管用:

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

您也可以使用这个(不带命名参数) :

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

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

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

[+-]?-可选的前导标志

不带前导零的整数,包括单个零

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

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

试试这个方法。

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

这将与:

  1. 1.2
  2. 12.3
  3. 123.4
  4. 一,二
  5. 十二,三
  6. 123,4

我不认为在写这篇文章的时候这个页面上的任何答案是正确的(其他地方的许多关于 SO 的建议也是错误的)。复杂的是,你必须匹配以下所有的可能性:

  • 没有小数点(即整数值)
  • 小数点前后的数字(如 0.3522.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+))

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

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

用于 javascript

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

这样也行 1.23 1234.22 0 0.12 12

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

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

  • '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+(e[+-]?\d+)?这是以’开头的数字

表达式结束

  • 以’开头的数字

第一个字符是点(在括号内,否则就是通配符)

一个或多个数字

这是一个可选的(0或1匹配结束’?’)科学记数法

  • 以数字开头的数字

一个或多个数字

我们可以选择在 ([.]\d*)?后面加一个点字符或者多个数字

这是一个可选的科学记数法

  • 科学记数法

指定指数的 e文本

[+-]?可选指数符号

一个或多个数字

所有这些加起来:

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

也接受 E:

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

(测试案例)

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

答案是这样的:

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

注意,我没有使用标志符号,如果你想要它和标志符号一起使用,它会是这样的:

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

这还可以分隔正则数字或十进制数字。

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

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

为了创建 float 正则表达式,我将首先创建“ 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})

对于那些谁搜索正则表达式将 确认一个 全部输入,应该是一个 签名花车点数字 每一个打出的字符的用户。

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

在 JS 中,我们使用 onkeydown/oninput事件来完成 + 以下 regex:

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

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

[+-]?((((\d+\.?\d*)|(\.\d+))([eE][+-]?\d+[fF]?)?)|((\d+\.\d*)|(\.\d+))[fF]?)
  • +/-签名
  • 只有数字,数字,数字或者数字
  • 带 e 或 E,+/-符号和数字的可选指数
  • 可选的 f 或 F 在结尾,但只有当数字包含一个。或指数
(\d*)(\.)*(\d+)

这将解析下面的代码。

11.00
12
.0

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

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

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

这是用于 javascript (如果两种语言之间有很大区别,可以使用 idk)

`int: /0|[1-9][0-9]*/`

花车:

`float:   /[0-9]+\.[0-9]+/`

如果你使用颤振,你可以使用 [0-9]([.]([0-9])*)? 这将解析 123.123

使用 C + + regex库,匹配 C 和 C + + (以及许多其他语言)编译器认为是浮点值有效表示的字符串:

在 C + + 和 #include <regex>中,你可以这样做:

std::regex r("[+-]?[0-9]+[.][0-9]*([e][+-]?[0-9]+)?");
return std::regex_match(value, r);

这比上面大多数与 C + + 相关的答案要简单得多。

它匹配字符串,根据 C + + 编译器,这些字符串被认为是浮点数的有效字符串表示形式。

意思是

1.
-1.

被认为是浮点数的有效表示,但是

.1
-.1

不是。

为了更详细地解释这个表达,它基本上由两部分组成:

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


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

第一部分很容易理解:

  • 可选(意味着0或1次出现)’+’或’-’字符
  • 至少一位数字,或多于一位数字
  • 一个文字“ .”字符,它是强制性的(否则您将得到一个整数的表示形式,而不是一个浮点值)
  • 如果希望“ .”是可选的,请将其更改为 [.]?
  • 后面跟着零个或多个数字

第二部分也是相当容易的一次打破。

  • 首先注意,表达式包含在圆括号中,后跟 ?。这意味着圆括号内的表达式必须匹配0或1次。(这意味着它是可选的。)
  • 里面有一个字母‘ e’必须匹配
  • 后跟可选的“ +”或“-”字符
  • 后面跟着1位或更多位数字

最后一部分 [+-]?[0-9]+是匹配整数的正则表达式。

为了匹配整数值,还可以使用:

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

注意 [.]后面的 ?

但请注意,这也将匹配的东西,如

+100e+100

这可能是一个不寻常的整数表示。虽然它在技术上是一个整数,但您可能不会期望它是一个匹配。

其他的答案提供了一个解决方案,如果你 不要想要这种行为。

为了确保整个字符串是匹配的,而不仅仅是包含匹配的字符串,请使用锚:

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

例子

没有主持人

Without anchor characters

还有主持人

enter image description here

带有可选的 '.'字符:

enter image description here

注意,如果不包含锚点字符(这可能不是您想要的) ,那么这将匹配字符串 .-100.1e100

当考虑这个问题时:

我的目标是验证用户输入,以确保它匹配浮点数的有效 C + + 字符串表示。因此,我假设您将使用锚点字符,并且您不会考虑字符串

hello world 3.14 this contains a floating point number

是一个有效的浮点数-因为尽管字符串包含一个浮点数,但整个字符串不是一个有效的浮点数。

如果您只想在较大的字符串/文本中检测浮点数,那么其他答案可能更适合您的需要。