与n个数字字符匹配的正则表达式,以及1或2个非数字字符

时间:2013-02-07 15:19:50

标签: php javascript regex

我一直在使用标准([0-9]+)模式匹配字符串中的数字,但现在有一个奇怪的边缘情况。我想匹配以下内容:

123
456个
0.123
123.
%123
31
14
第二
100.55
555.10

在上述情况下,非数字字符为:


小号
^ h
ñ
d

但他们可能是各种各样的角色 想法?

JS或PHP会很棒。

4 个答案:

答案 0 :(得分:3)

从一个可以获得你想要的模式开始:

\d+

现在您还想匹配十进制数字,因此请扩展您的选项:

这个匹配数字后跟一个可选的小数点

\d+\.?

这个匹配十进制数字:

\d*\.\d+

加入两者将为您提供一个完整的数字匹配模式(如果您不想匹配000.0000等数字,这可能仍有问题):

(?:\d+\.?|\d*\.\d+)

现在是棘手的部分。您需要确定完全其他字符可能是前缀或后缀的数字。

鉴于这个例子,我将做出以下假设:

  • %可以为小数前缀,但不带后缀
  • stndrdth可能仅后缀整数

鉴于这些假设:

%个字符可以选择匹配小数:

(?:%?(?:\d+\.?|\d*\.\d+))

带有后缀的整数可以匹配(这不验证后缀,1nd是有效的):

(?:\d+(?:st|nd|rd|th)

加入这两种模式会产生:

(?:(?:%?(?:\d+\.?|\d*\.\d+))|(?:\d+(?:st|nd|rd|th)))

当然,您可能希望将匹配限制为整个字符串:

/^(?:(?:%?(?:\d+\.?|\d*\.\d+))|(?:\d+(?:st|nd|rd|th)))$/

答案 1 :(得分:2)

我尝试为所有情况创建几条规则:

(\d+(?:\.\d*)?)        // 123 ; 123. ; 123.45
([%.]\d+)              // %123 ; .123
(\d+(?:st|nd|th))      // 31st ; 2nd ; 14th

然后混合:

((?:\d+(?:\.\d*)?)|(?:[%.]\d+)|(?:\d+(?:st|nd|th)))

如果你想要更短的东西,你可以简单地使用([%.\dshnd]+),但这会捕获许多不想要的条目,比如%%123%%

答案 2 :(得分:1)

如果您正在寻找您期望的模式验证(例如日期?),您可以这样做:

[\d.%]*(nd|st|th){0,1}

如果您知道%的位置是前导,或者您只有一个小数,或者如果您不想要st / nd / etc,则可以这样改进:

([%]){0,1}[\d]*((((\.[\d]+){0,1}){0,1})|((nd|st|th|rd){0,1}))

我仍然没有在任何地方处理空间,但我想您可以看到如何添加它?此外,您可能希望确保第1对第11等等 - 如果您担心进一步改进验证可以开始类似日期(您可能更好地谷歌):

([023]){0,1}1st|([02]){0,1}2nd|([02]){0,1}3rd|(11|12|13|30|(([012]){0,1}(([4-9])|0))th)

有一些额外的括号可以尝试尽可能清楚

答案 3 :(得分:1)

这个适合您的需求:

^([.]|%)?\d+(((?<=^1)|(?<!^1)1)st|(?<!^1)((?<=^2)|2)nd|(?<!^1)((?<=^3)|3)rd|th|[.]\d*)?$

Demo

^                            # start of the string
([.]|%)?                     # . or % {0 or 1 time}
\d+                          # any digit {1 or more times}
(
    ((?<=^1)|(?<!^1)1)st     # either (1) or (ending with 1 but not 11) followed by st
    |(?<!^1)((?<=^2)|2)nd    # either (2) or (ending with 2 but not 12) followed by nd
    |(?<!^1)((?<=^3)|3)rd    # either (3) or (ending with 3 but not 13) followed by rd
    |th                      # th
    |[.]\d*                  # . followed by (a digit {0 or more times})
)?                           # {0 or 1 time}
$                            # end of the string

请注意,JS无法理解此正则表达式,因为它不支持lookbehinds(?<=?<!)。