我有一个匹配浮点数的任务。我为它写了以下正则表达式:
[-+]?[0-9]*\.?[0-9]*
但是,它返回一个错误:
Invalid escape sequence (valid ones are \b \t \n \f \r \" \' \\ )
据我所知,我们还需要为.
使用转义字符。请纠正我错在哪里。
使用[.]
而不是\.
和[0-9]
而不是\d
来避免在某些语言中逃避问题(如Java)。
感谢the nameless one最初认识到这一点。
用于匹配浮点数的一个相对简单的模式是
[+-]?([0-9]*[.])?[0-9]+
这将匹配:
123
123.456
.456
如果你还想匹配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,框架或库。
(顺便说一下,为了帮助减少混淆,许多人已经开始使用“regex”或“regexp”来描述这些增强的匹配语言。有关更多信息,请参阅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
),空心方括号(\\[
)和反斜杠(\\\\
或[\\]
)。
(提示:这比你想象的要难)
匹配一个数字是你认为用正则表达式很容易的事情之一,但它实际上非常棘手。让我们一块一块地看看你的方法:
[-+]?
匹配可选的-
或+
[0-9]*
匹配0个或更多个连续数字
\.?
匹配可选的.
[0-9]*
匹配0个或更多个连续数字
首先,我们可以通过对数字使用character class shorthand来清理这个表达式(请注意,这也容易受到上面提到的转义问题的影响):
[0-9]
= \d
我将在下面使用\d
,但请记住它与[0-9]
的意思相同。 (嗯,实际上,在某些引擎中,\d
将匹配所有脚本中的数字,因此它将比[0-9]
更匹配,但在您的情况下这可能并不重要。)
现在,如果仔细观察,你会发现你的模式的每一部分都是可选的。此模式可以匹配0长度的字符串;由+
或-
组成的字符串;或者,一个仅由.
组成的字符串。这可能不是你想要的。
要解决这个问题,首先要使用最小的必需字符串“锚定”正则表达式,这可能是一个数字:
\d+
现在我们要添加小数部分,但它不会出现在您认为可能的位置:
\d+\.?\d* /* This isn't quite correct. */
这仍然会匹配像123.
这样的值。更糟糕的是,它有一个关于它的tinge of evil。这段时间是可选的,这意味着你有两个并排的重复课程(\d+
和\d*
)。如果以错误的方式使用,将系统打开到DoS攻击,这实际上可能是危险的。
要解决这个问题,不要将句点视为可选,我们需要根据需要对其进行处理(分隔重复的字符类),而是将整个小数部分设为可选:
\d+(\.\d+)? /* Better. But... */
现在看起来好多了。我们需要在第一个数字序列和第二个数字序列之间有一段时间,但是有一个致命的缺陷:我们无法匹配.123
,因为现在需要一个前导数字。
这实际上很容易修复。我们不需要将数字的“十进制”部分作为可选项,而是将其视为一系列字符:一个或多个数字可以以.
作为前缀,可以使用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
。还要记住,某些引擎允许您设置标志,这些标志会更改^
和$
的定义,匹配行的开头/结尾而不是整个输入的开头/结尾。这通常不是默认值,而是要注意这些标志。
[+/-] [0-9]*.[0-9]+
试试这个解决方案
对于JavaScript
const test = new RegExp('^[+]?([0-9]{0,})*[.]?([0-9]{0,2})?$','g');
哪个适用于1.23 1234.22 0 0.12 12
您可以更改{}
中的部件以获得十进制长度和小数前面的不同结果。这用于输入输入数字和检查每个输入,因为您只键入允许传递的内容。
我不认为在撰写本文时,本页面上的任何答案都是正确的(在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+))
我不认为有一种方法可以避免(...)|(...)
构造而不允许任何不包含数字的东西,或者禁止在小数点之前没有数字或者之后没有数字的可能性之一。
显然,在实践中,您需要在正则表达式本身或使用它的代码中处理尾随或前面的空格。
你需要的是:
[\-\+]?[0-9]*(\.[0-9]+)?
我转义了“+”和“ - ”符号,并将小数与其后面的数字分组,因为类似于“1”。不是有效的数字。
这些更改将允许您匹配整数和浮点数。例如:
0
+1
-2.0
2.23442
这很简单:你使用过Java,你应该使用\\.
而不是\.
(在Java中搜索字符转义)。
这个对我有用:
(?P<value>[-+]*\d+\.\d+|[-+]*\d+)
你也可以使用这个(没有命名参数):
([-+]*\d+\.\d+|[-+]*\d+)
使用一些在线正则表达式测试仪进行测试(例如regex101)
[+-]?(([1-9][0-9]*)|(0))([.,][0-9]+)?
[+-]?
- 可选的主要标志
(([1-9][0-9]*)|(0))
- 不带前导零的整数,包括单个零
([.,][0-9]+)?
- 可选的小数部分
^[+]?([0-9]{1,2})*[.,]([0-9]{1,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运算符('|')以确保我们排除'。'从匹配。
[+-]?
+/- 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+)?)
在C ++中使用正则表达式库
答案就是这样的:
[0-9]?([0-9]*[.])?[0-9]+
请注意,我没有使用符号符号,如果你想要它带有符号符号,那就是:
[+-]?([0-9]*[.])?[0-9]+
这也分隔了常规数字或十进制数字。