浮点数的正则expression式
我有一个任务来匹配浮点数。 我写了下面的正则expression式:
[-+]?[0-9]*\.?[0-9]*
但它显示一个错误说:
Invalid escape sequence (valid ones are \b \t \n \f \r \" \' \\ )
但根据我的知识,我们需要使用转义字符.
也。 请纠正我错在哪里。
TL; DR
使用[.]
而不是\.
和[0-9]
而不是\d
以避免在某些语言(如Java)中出现转义问题。
匹配浮点数的正确模式是
[+-]?([0-9]*[.])?[0-9]+
这将匹配:
-
123
-
123.456
-
.456
看一个工作的例子
如果你想validation一个input是一个数字(而不是在input中find一个数字),那么你应该用^
和$
来包围这个模式,就像这样:
^[+-]?([0-9]*[.])?[0-9]+$
注意上面的expression式不会validation
123.
。 如果你想包括这样的input有效,那么你需要使用^[+-]?([0-9]+([.][0-9]*)?|[.][0-9]+)$
请参阅pkeller的答案来更全面地解释这种模式
不规则正则expression式
在大多数现代语言,API,框架,库等中实现的“正则expression式”是基于在forms语言理论中发展的概念。 但是,软件工程师添加了许多扩展,使得这些实现远远超出了正式的定义。 所以,虽然大多数正则expression式引擎相似,但实际上并没有标准。 出于这个原因,很多取决于你正在使用什么语言,API,框架或库。
也就是说,大多数正则expression式引擎(实际上,就我所知,所有这些引擎)都会接受\.
。 最有可能的是,逃跑有一个问题。
转义的麻烦
(感谢最初认识到这一点的无名之辈 )
有些语言内置了对正则expression式的支持, 比如JavaScript 。 对于那些不这样做的语言,转义可能是一个问题。
这是因为你基本上是在一种语言的语言编码。 例如,Java在其string中使用\
作为转义字符,因此如果要在string中放置文字反斜线字符,则必须将其转义:
// creates a single character string: "\" String x = "\\";
但是,正则expression式也使用\
字符进行转义,所以如果要匹配文字\
字符,则必须将其转义为正则expression式引擎,然后再转义为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 = "\\.";
所有这些逃脱可能会变得非常混乱。 如果你正在使用的语言支持原始string ,那么你应该使用这些来减less反斜杠的数量,但不是所有的语言(最显着的是:Java)。 幸运的是,有一个替代scheme可以在一段时间内发挥作用:
String correctPattern = "[.]";
对于一个正则expression式引擎, \.
和[.]
意思完全一样的东西。 请注意,这不适用于所有情况,如换行( \\n
),方括号( \\[
]和反斜线( \\\\
或[\\]
))。
关于匹配数字的一个注记
(提示:比你想象的要难)
使用正则expression式匹配数字就是其中一个你认为很容易的事情,但实际上它非常复杂。 让我们一步一步看看你的方法:
[-+]?
匹配可选-
或+
[0-9]*
匹配0个或更多的连续数字
\.?
匹配一个可选的.
[0-9]*
匹配0个或更多的连续数字
首先,我们可以通过对数字使用一个字符类速记来清理这个expression式(注意这也容易出现上面提到的转义问题):
[0-9]
= \d
我将在下面使用\d
,但是要记住它和[0-9]
是一样的。 (实际上,在某些引擎中, \d
会匹配所有脚本中的数字,所以它会匹配[0-9]
以上的数字,但这可能对您而言并不重要)。
现在,如果仔细看看,你会发现模式的每一个部分都是可选的 。 该模式可以匹配0长度的string; 一个仅由+
或-
组成的string; 或者,一个仅由a组成的string.
。 这可能不是你想要的。
为了解决这个问题,首先使用最小的必需string“锚定”正则expression式,这可能是一个数字:
\d+
现在我们要添加小数部分,但它不会到你认为可能的地方:
\d+\.?\d* /* This isn't quite correct. */
这仍然会匹配像123.
一样的值。 更糟糕的是,它有一个邪恶的色彩 。 这段时间是可选的,意味着你有两个重复的类并排( \d+
和\d*
)。 如果以错误的方式使用,这实际上是危险的,打开您的系统到DoS攻击。
为了解决这个问题,我们需要按照需要处理(重复的字符类别),而不是把期间视为可选的,而是将整个小数部分设为可选:
\d+(\.\d+)? /* Better. But... */
现在看起来好多了 我们需要在第一个数字序列和第二个数字序列之间的一段时间,但是有一个致命的缺陷:我们不能匹配.123
因为现在需要一个前导数字。
这实际上很容易修复。 我们不需要将数字的“十进制”部分设置为可选,而是将其视为一系列字符:一个或多个可能以a开头的数字.
可能以0或更多数字为前缀:
(\d*\.)?\d+
现在我们只是添加符号:
[+-]?(\d*\.)?\d+
当然,这些斜线在Java中是非常烦人的,所以我们可以用我们的长型字符类replace:
[+-]?([0-9]*[.])?[0-9]+
匹配与validation
这已经出现在评论中几次了,所以我添加了一个关于匹配和validation的附录。
这里描述的正则expression式将匹配目标string中的一个或多个数字。 所以给了input:
apple 1.34 pear 7.98 version 1.2.3.4
正则expression式将匹配1.34
, .3
和.4
。
但是,如果您要validation给定的input是一个数字,而不是一个数字,那么您需要将它包装在锚标记中:
^[+-]?([0-9]*[.])?[0-9]+$
这将确保整个inputstring匹配正则expression式。 (请注意,一些正则expression式引擎允许您设置标志,以改变^
和$
的定义,匹配行的开始/结束与整个input的开始/结束。)
我不认为在写这篇文章的时候,这个页面上的任何答案都是正确的(其他许多其他build议也是错误的)。 复杂的是,你必须匹配所有以下的可能性:
- 没有小数点(即整数值)
- 小数点前后的数字(例如
22.165
) - 仅在小数点之前的数字(例如
1234.
)。 - 仅在小数点后的数字(例如
.0
,.5678
)
同时,您必须确保在某个地方至less有一个数字,即以下内容不被允许:
- 小数点本身
- 没有数字的有符号小数点(即
+.
或-.
) -
+
或-
自己 - 一个空的string
这看起来很棘手,但是寻找灵感的一个方法是查看OpenJDK源代码的java.lang.Double.valueOf(String)
方法(从http://hg.openjdk.java.net/jdk8/jdk8开始;java.lang.Double.valueOf(String)
/ jdk ,点击“浏览”,向下浏览/src/share/classes/java/lang/
并findDouble
类)。 这个类包含的很长的正则expression式可以满足OP可能没有的各种可能性,但是为了简单起见,它忽略了处理NaN,无穷大,hex符号和指数的部分,并且使用\d
而不是POSIX对于单个数字的符号,我可以减less正则expression式的重要部分为没有指数的带符号的浮点数:
[+-]?((\d+\.?\d*)|(\.\d+))
我不认为有一种方法可以避免(...)|(...)
构造,而不允许不包含任何数字的东西,或者禁止在小数点之前没有数字或者没有数字的可能性之后。
显然在实践中,你需要在正则expression式本身或使用它的代码中迎合尾随或前面的空格。
你需要的是:
[\-\+]?[0-9]*(\.[0-9]+)?
我逃脱了“+”和“ – ”符号,并将小数点后面的数字分组,因为像“1” 不是一个有效的数字。
更改将允许您匹配整数和浮点数。 例如:
0 +1 -2.0 2.23442
这很简单:你已经使用Java,你应该使用\\.
而不是\.
(在Java中search字符转义)。
这个为我工作:
(?P<value>[-+]*\d+\.\d+|[-+]*\d+)
你也可以使用这个(没有命名参数):
([-+]*\d+\.\d+|[-+]*\d+)
使用一些在线正则expression式testing器来testing它(例如regex101)
^[+]?([0-9]{1,2})*[.,]([0-9]{1,1})?$
这将匹配:
- 1.2
- 12.3
- 1,2
- 12,3
[+-]?(([1-9][0-9]*)|(0))([.,][0-9]+)?
[+-]?
– 可选的领先标志
(([1-9][0-9]*)|(0))
– 不包含前导零的整数,包括单个零
([.,][0-9]+)?
– 可选的小数部分
[+/-] [0-9]*.[0-9]+
试试这个解决scheme