1

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

123
456
.123
123.
%123
31
14
2
100.55
555.10

在上述情况下,非数字字符是:
.
%
s
h
n
d

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

JS 或 PHP 会很棒。

4

4 回答 4

3

从一个能得到你想要的东西的模式开始:

\d+

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

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

\d+\.?

这个匹配十进制数字:

\d*\.\d+

加入两者将为您提供可靠的数字匹配模式(如果您不想匹配类似的数字,这可能仍然存在问题000.0000):

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

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

给定示例,我将做出以下假设:

  • %可以前缀小数,但没有后缀
  • st, nd, rd, 并且th只能作为整数后缀

鉴于这些假设:

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

(?:%?(?:\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)))$/
于 2013-02-07T15:56:13.110 回答
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%%.

于 2013-02-07T15:35:34.240 回答
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)

那里有一些额外的括号,试图尽可能清楚

于 2013-02-07T15:34:53.497 回答
1

这一款适合您的需求:

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

演示

^                            # 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 将无法理解此正则表达式,因为它不支持后视(?<=?<!)。

于 2013-02-07T16:02:41.350 回答