我有一个任务来匹配浮点数。我为此编写了以下正则表达式:
[-+]?[0-9]*\.?[0-9]*
但是,它返回一个错误:
Invalid escape sequence (valid ones are \b \t \n \f \r \" \' \\ )
据我所知,我们还需要使用转义字符.
。请纠正我哪里错了。
我有一个任务来匹配浮点数。我为此编写了以下正则表达式:
[-+]?[0-9]*\.?[0-9]*
但是,它返回一个错误:
Invalid escape sequence (valid ones are \b \t \n \f \r \" \' \\ )
据我所知,我们还需要使用转义字符.
。请纠正我哪里错了。
使用[.]
代替\.
和[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 定义的标志^
,$
匹配行的开头/结尾而不是整个输入的开头/结尾。这通常不是默认设置,但请注意这些标志。
我不认为在撰写本文时此页面上的任何答案都是正确的(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+))
我认为没有一种方法可以避免(...)|(...)
构造,而不允许不包含数字的内容,或者禁止小数点前没有数字或小数点后没有数字的可能性之一。
显然,在实践中,您需要在正则表达式本身或使用它的代码中处理尾随或前面的空格。
我想匹配大多数语言认为有效的数字(整数和浮点数):
'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+)?)
(测试用例)
This is simple: you have used Java and you ought to use \\.
instead of \.
(search for character escaping in Java).
你需要的是:
[\-\+]?[0-9]*(\.[0-9]+)?
我转义了“+”和“-”符号,并将小数与其后面的数字分组,因为类似于“1”。不是有效数字。
这些更改将允许您匹配整数和浮点数。例如:
0
+1
-2.0
2.23442
这个对我有用:
(?P<value>[-+]*\d+\.\d+|[-+]*\d+)
您也可以使用这个(没有命名参数):
([-+]*\d+\.\d+|[-+]*\d+)
使用一些在线正则表达式测试器来测试它(例如 regex101 )
^[+-]?([0-9]{1,})[.,]([0-9]{1,})$
这将匹配:
这将捕获 C/C++ 代码中识别的浮点数:
[+-]?((((\d+\.?\d*)|(\.\d+))([eE][+-]?\d+[fF]?)?)|((\d+\.\d*)|(\.\d+))[fF]?)
(\d*)(\.)*(\d+)
这将解析以下内容。
11.00
12
.0
必须有一个数字。小数点和小数点前的数字是可选的。
对于 javascript
const test = new RegExp('^[+]?([0-9]{0,})*[.]?([0-9]{0,2})?$','g');
这适用于 1.23 1234.22 0 0.12 12
您可以更改 中的部分{}
以获得小数长度和小数前面的不同结果。这在输入中用于输入数字并在您键入时检查每个输入,仅允许通过的内容。
[+/-] [0-9]*.[0-9]+
试试这个解决方案。
在 C 语言中,答案是这样的:
[+-]?((\d+\.?\d*)|(\.\d+))(([eE][+-]?)?\d+)?[fFlL]?
对于那些搜索将验证整个输入的正则表达式的人,该输入应该是用户键入的每个字符上的有符号浮点数。
即符号首先出现(应该匹配并且有效),然后是所有数字(仍然匹配并且有效)及其可选的小数部分。
在 JS 中,我们使用onkeydown
/oninput
事件来做到这一点 + 以下正则表达式:
^[+-]?[0-9]*([\.][0-9]*)?$
[+-]?(([1-9][0-9]*)|(0))([.,][0-9]+)?
[+-]?
- 可选的领先标志
(([1-9][0-9]*)|(0))
- 不带前导零的整数,包括单个零
([.,][0-9]+)?
- 可选小数部分
在 c 表示法中,浮点数可以以下列形式出现:
为了创建浮点正则表达式,我将首先创建“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})
在 C++ 中使用正则表达式库
答案是这样的:
[0-9]?([0-9]*[.])?[0-9]+
请注意,我不使用符号符号,如果您想要它带有符号符号,它会这样做:
[+-]?([0-9]*[.])?[0-9]+
这也将常规数字或十进制数字分开。