使用[.]而不是\.和[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是否与正则表达式相同?欲了解更多信息,请访问RexEgg.com。)
尽管如此,大多数regex引擎(实际上,据我所知,所有的引擎)都会接受。\...很可能,逃跑有问题。
逃跑的麻烦
有些语言内置了对regexes的支持,比如JavaScript..对于那些没有转义的语言来说,转义可能是个问题。
这是因为你基本上是在用一种语言在一种语言中编码。例如,Java使用\作为其字符串中的转义字符,因此,如果要在字符串中放置文字反斜杠字符,则必须转义它:// creates a single character string: "\"String x = "\\";
然而,雷克斯也使用\用于转义的字符,因此如果要匹配文字\字符时,必须为regexe引擎转义它,然后再为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" errorString wrongPattern = "\.";// will result in the string "
\."String correctPattern = "\\.";
所有这些逃逸都会让人很困惑。如果您正在使用的语言支持原始字符串,然后您应该使用这些来减少反斜杠的数量,但并不是所有语言都这样做(最显著的是:Java)。幸运的是,有一种替代方案在某些时候会起作用:String correctPattern = "[.]";
作为一个正则引擎,\.和[.]意思完全一样。注意,这并不适用于每种情况,比如换行符(\\n),开放式方括号(\\[)和反斜杠(\\\\或[\\]).
关于匹配数的一个注记
(提示:这比你想象的要难)
匹配一个数字是其中之一,你会认为使用regex是相当容易的,但它实际上是相当棘手的。让我们看一看你的方法,一片片地:[-+]?
匹配一个可选的-或+[0-9]*
匹配0或更多顺序数字\.?
匹配一个可选的.[0-9]*
匹配0或更多顺序数字
首先,我们可以使用字符类速记对于数字(请注意,这也容易受到上述转义问题的影响):
[0-9] = \d
我要用\d下面,但请记住,它的含义与[0-9]..(实际上,在一些发动机中\d将匹配所有脚本中的数字,因此它将比[0-9]威尔,但这在你的情况下可能并不重要。)
如果你仔细看一下,你会发现模式的每个部分都是可选的。..此模式可以匹配0长度的字符串;字符串仅由+或-或者,仅由...这可能不是你想要的。
要解决这一问题,首先使用最低要求的字符串(可能是个位数)“锚定”正则表达式是很有帮助的:\d+
现在我们想要添加小数部分,但它不适用于您认为可能的地方:\d+\.?\d* /* This isn't quite correct. */
这仍然将匹配如下所示的值123...更糟的是恶毒关于这件事。句点是可选的,这意味着您同时拥有两个重复的类(\d+和\d*)。这实际上可能是危险的,如果使用只是错误的方式,打开您的系统直至拒绝服务攻击。
要解决这个问题,我们需要将句点视为可选的,而不是将其视为可选的(分隔重复字符类),并将整个十进制部分改为可选的:\d+(\.\d+)? /* Better. But... */
现在看起来好多了。我们需要一个介于第一个数字序列和第二个数字序列之间的句点,但是有一个致命的缺陷:我们无法匹配.123因为现在需要一个前导数字。
这其实很容易解决。而不是将数字的“十进制”部分设置为可选,我们需要将其看作一个字符序列:1或更多的数字,这些数字的前缀可能是.可以0或更多个数字作为前缀:(\d*\.)?\d+
现在我们只添加一个标志:[+-]?(\d*\.)?\d+
当然,这些斜杠在Java中非常烦人,因此我们可以在长格式字符类中替换:[+-]?([0-9]*[.])?[0-9]+
匹配与验证
这已经在评论中出现了几次,所以我要添加一个关于匹配与验证的增编。
目标匹配就是在输入中找到一些内容(“大海捞针”)。目标验证以确保输入采用预期格式。
雷吉斯,根据他们的天性,只有匹配短信。给定一些输入,他们要么找到匹配的文本,要么找不到。但是,通过用锚标记“抓取”一个表达式到输入的开头和结尾(^和$),我们可以确保没有找到匹配,除非整个输入与表达式匹配,有效地使用regexes验证.
上述正则表达式([+-]?([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不会找到匹配的。
注意,一些regex引擎有一个validate, isMatch或者类似的函数,它本质上执行我所描述的自动返回true如果找到匹配false如果没有找到匹配的。还请记住,某些引擎允许您设置更改^和$匹配行的开始/结束,而不是整个输入的开始/结束。这通常不是默认的,但是要注意这些标志。