我一直在使用标准([0-9]+)
模式匹配字符串中的数字,但现在有一个奇怪的边缘情况。我想匹配以下内容:
123
456个
0.123
123.
%123
31
14
第二
100.55
555.10
在上述情况下,非数字字符为:
。
%
小号
^ h
ñ
d
但他们可能是各种各样的角色 想法?
JS或PHP会很棒。
答案 0 :(得分: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)))$/
答案 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*)?$
^ # 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(?<=
和?<!
)。