浮点数的正则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式不会validation123. 如果你想包括这样的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. 1.2
  2. 12.3
  3. 1,2
  4. 12,3
 [+-]?(([1-9][0-9]*)|(0))([.,][0-9]+)? 

[+-]? – 可选的领先标志

(([1-9][0-9]*)|(0)) – 不包含前导零的整数,包括单个零

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

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

试试这个解决scheme