我有一个任务要匹配浮点数。我为此编写了以下正则表达式:
[-+]?[0-9]*\.?[0-9]*
但是,它返回一个错误:
Invalid escape sequence (valid ones are \b \t \n \f \r \" \' \\ )
据我所知,我们还需要使用转义字符.
。请纠正我哪里我错了。
[-+]?([0-9]*[.])?[0-9]+([eE][-+]?\d+)?
如果您也想采用指数表示法,例如3.023e-23
我有一个任务要匹配浮点数。我为此编写了以下正则表达式:
[-+]?[0-9]*\.?[0-9]*
但是,它返回一个错误:
Invalid escape sequence (valid ones are \b \t \n \f \r \" \' \\ )
据我所知,我们还需要使用转义字符.
。请纠正我哪里我错了。
[-+]?([0-9]*[.])?[0-9]+([eE][-+]?\d+)?
如果您也想采用指数表示法,例如3.023e-23
Answers:
使用[.]
代替\.
和[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,框架或库。
(顺便说一句,为了减少混乱,许多人开始使用“ 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
),方括号(\\[
)和反斜杠(\\\\
或[\\]
)。
(提示:这比您想象的要难)
使用正则表达式,匹配数字是您认为很容易的事情之一,但实际上非常棘手。让我们一步一步地看一下您的方法:
[-+]?
匹配可选-
或+
[0-9]*
匹配0个或多个连续数字
\.?
搭配可选 .
[0-9]*
匹配0个或多个连续数字
首先,我们可以通过使用数字的字符类缩写来稍微整理一下此表达式(请注意,这也容易受到上述转义问题的影响):
[0-9]
= \d
我将在\d
下面使用,但请记住,它的含义与相同[0-9]
。(实际上,在某些引擎中,\d
它将匹配所有脚本中的数字,因此它会比匹配的更多[0-9]
,但这在您的情况下可能并不重要。)
现在,如果仔细看一下,您会发现模式的每个部分都是可选的。此模式可以匹配长度为0的字符串;仅由+
or 组成的字符串-
;或者,仅由组成的字符串.
。这可能不是您想要的。
要解决此问题,从用最小的必需字符串(可能是一个数字)“固定”正则表达式开始会很有帮助:
\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
如果没有发现匹配。也请记住,有些引擎允许你改变它的定义组标志^
和$
,一条线的开始/结束,而不是整个输入的开始/结束匹配。通常这不是默认值,但是请注意这些标志。
\d+(\.\d*)?|\.\d+
/[-+]?(\d*[.])?\d+/.test("1.bc") // returns true
1.
匹配。如果只想在整个输入匹配的情况下进行匹配,则在正则表达式的开头和结尾处添加^
和$
。
[-+]?(([0-9]*[.]?[0-9]+([ed][-+]?[0-9]+)?)|(inf)|(nan))
e / d表示浮点数/双精度浮点数。不要忘记对正则表达式使用折痕标志
我认为在撰写本文时,此页面上的任何答案都不正确(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+))
我不认为有一种避免(...)|(...)
构造的方法,就是不允许不包含数字的东西,或者禁止小数点前没有数字或小数点后没有数字的一种可能性。
显然,实际上,您将需要在正则表达式本身或使用它的代码中满足尾随或前导空格。
[+-]?((?=\.?\d)\d*\.?\d*)
来避免这种交替吗?它使用了前瞻性...
您需要的是:
[\-\+]?[0-9]*(\.[0-9]+)?
我转义了“ +”和“-”符号,并且也将小数点后面的数字分组,因为类似“ 1”。不是有效数字。
这些更改将允许您匹配整数和浮点数。例如:
0
+1
-2.0
2.23442
.1
,即使这种输入被普遍认为是正确的,也不允许这样做。
-
和+
,它们不是数字。正则表达式很棘手!:)
\.
是行不通的。
我想匹配大多数语言所认为的有效数字(整数和浮点数):
'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+)?)
也要接受E
:
[+-]?(\d+([.]\d*)?([eE][+-]?\d+)?|[.]\d+([eE][+-]?\d+)?)
(测试用例)
这很简单:您已经使用过Java,应该使用\\.
而不是\.
(在Java中搜索字符转义)。
^[+]?([0-9]{1,2})*[.,]([0-9]{1,1})?$
这将匹配:
[+-]?(([1-9][0-9]*)|(0))([.,][0-9]+)?
[+-]?
-可选的前导标志
(([1-9][0-9]*)|(0))
-不带前导零的整数,包括单零
([.,][0-9]+)?
-可选的小数部分
用符号表示时,浮点数可能会出现以下形状:
为了创建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})
[+/-] [0-9]*.[0-9]+
试试这个解决方案。