文章目录▼CloseOpen
- 先搞懂:为什么匹配0-10的正则总写错?
- 直接抄作业:匹配0-10的正则怎么写?分场景讲
- 不同语言怎么用?别踩API的坑
- 避坑提醒:这3个细节90%的人会忽略
- 为什么[0-10]匹配不了10?
- 加^和$到底有什么用?
- JavaScript和Python里用这个正则有区别吗?
- 输入带空格或换行符怎么办?
- 怎么避免匹配到像100里的10?
先搞懂:为什么匹配0-10的正则总写错?
我朋友的错误,其实踩了正则里最常见的两个“坑”——把字符集当选择符用,没给范围画边界。先讲第一个坑:他写的[0-10]
,你猜这玩意儿实际匹配啥?字符集里的-
是范围符,0-1
是0和1,后面加个0就是重复的0——所以这个表达式其实只匹配0、1这两个数字,跟10压根儿没关系!我当时跟他说的时候,他瞪着眼睛问:“那我要匹配10怎么办?”——这就是第二个误区:字符集只能处理单个字符或连续范围,10是两个字符,得用|
(或者)来分开,不能塞在字符集里。
再讲第二个坑:没加^
和$
。他一开始觉得“反正表单输入的是数字,不会有其他字符”,结果用户复制粘贴时带了个空格,比如“ 10 ”,正则没加边界,直接把空格当成无关字符,匹配到“10”就算对了——更离谱的是,有次用户输入“10a”,他的正则也通过了,因为“10”在字符串里存在。我跟他说:“^
是开头,$
是 加了这俩,相当于给正则画了个圈——你要找的是整个字符串都是0-10的数,不是里面有一段是。”他试了加之后,立马解决了一半问题,但又出新问题:“那10怎么匹配不上?”——哦,对了,他还没改字符集的问题,把正则写成^[0-10]$
,我直接给他发了个表情包:“你是要气死我吗?”
其实这些错误,本质是没搞懂正则的“规则”——它不是你想的“写个范围就行”,而是要“拆成一个个可能的情况,用正确的符号连起来”。我后来给朋友举了个例子:“你要找的是三类数:0、1-9的单个数字、10——这三类是并列的,所以要用|
分开,每一类都要加边界,确保是完整的字符串。”他这才恍然大悟:“哦,原来我之前是把三类数揉成一团了!”
直接抄作业:匹配0-10的正则怎么写?分场景讲
现在直接给你能落地的方案——我把不同场景的正则整理成了表格,连为什么这么写都标清楚,你对着用就行:
场景 | 正则表达式 | 说明 |
---|---|---|
纯数字输入(如表单框) | ^0$|^10$|^[1-9]$ | 匹配0、1-9单数字、10,加边界确保完整 |
带前后空格(如复制粘贴) | ^s0s$|^s10s$|^s[1-9]s$ | s匹配空格/制表符,适合输入不干净的场景 |
提取文本中的数字(如文章) | b0b|b10b|b[1-9]b | b是单词边界,避免匹配“100”里的“10” |
我朋友看了这个表格,第一反应是:“第三个场景的b是什么?”——我跟他说:“比如你要从文章里找‘评分10分’里的‘10’,用b的话,就不会把‘100分’里的‘10’算进去——b相当于‘单词的缝隙’,只有当数字前后不是字母、数字或下划线时,才会匹配。”他试了之后,说:“哦,原来如此!我之前用^和$,结果文章里的数字全没匹配到,现在换成b,一下就对了!”
不同语言怎么用?别踩API的坑
再讲不同语言的差异——比如JavaScript里,验证表单输入可以写:
function validateNumber(input) {
const regex = /^0$|^10$|^[1-9]$/;
return regex.test(input.trim()); // 先trim掉空格,更稳妥
}
而Python里,要用re.fullmatch
(匹配整个字符串):
import re
def validate_number(input_str):
pattern = r'^0$|^10$|^[1-9]$'
return re.fullmatch(pattern, input_str.strip()) is not None
我朋友一开始用了Python的re.match
,结果“01”也匹配通过了——我跟他说:“re.match
是从开头开始匹配,但如果整个字符串没匹配完,就算失败。比如‘01’,开头是0,但后面还有1,所以会失败——你之前的问题是用了re.search
,它会找字符串里的任意匹配,比如‘01’里的‘0’,所以才会错。”他改了之后,说:“原来API的细节这么重要!”
避坑提醒:这3个细节90%的人会忽略
最后给你提3个我朋友踩过的坑,帮你省点时间:
s
改成[sn]
——s
不包括换行符,我朋友没改,结果用户输入“10n”(后面带换行),正则没匹配到,查了半小时才发现。其实写正则没什么捷径,就是“拆情况、守规则、测边界”——我朋友现在写这个正则,比写“hello world”还熟。对了,如果你按这些方法试了,遇到奇怪的问题,比如某个场景匹配不上,欢迎留言告诉我——我帮你一起揪出问题,毕竟踩过坑的人,最知道怎么填坑!
你有没有过这种情况?想从文章里找“用户打了10分”的10,结果把“这款产品卖了100件”里的10也揪出来了?我之前帮运营的朋友做过一次用户评论分析,就踩过这个坑——她要统计“打10分”的评论数量,一开始用的正则没加b,结果统计出来的数比实际多了快一倍,后来查了半天才发现,把“100字的详细好评”里的“10”也算进去了。
其实问题出在“正则默认不管前后字符”——它只会找字符串里有没有符合的片段,不会管这个片段是不是“独立的数字”。那怎么让正则只认“单独的10”?得给数字装个“边界探测器”,也就是b(单词边界)。这玩意儿的作用特别好理解:只有当数字前后不是字母、数字或者下划线的时候,才会把这个数字算进去。比如“用户打了10分”里的10,前面是“打了”(汉字,不是单词字符),后面是“分”(同样不是),所以b会把这个10认出来;但“100件”里的10,后面跟着0(数字,属于单词字符),所以b就不会匹配——因为后面的0和10是“连在一起的”,不算“边界”。
我后来给朋友改的正则是b0b|b10b|b[1-9]b,她用这个再跑数据,直接把“100”里的10筛掉了,统计结果一下就准了。对了,用的时候还有个小细节:如果是在JavaScript里提取,得加个g全局匹配,不然只能找到第一个符合的数字;Python里用re.findall的时候,记得把正则写成r’b0b|b10b|b[1-9]b’——前面加r是 raw string,避免转义字符搞事。
还有个情况你可能碰到:如果数字前后是下划线,比如“_10_”,b也不会匹配,因为下划线属于“单词字符”(正则里把字母、数字、下划线统称单词字符)。不过这种场景一般很少见,比如用户评论里几乎不会出现“_10_”这种表达,所以不用太担心。要是真碰到了,再调整正则就行——比如把b换成(?<![0-9])和(?![0-9])(负向断言),不过那是更复杂的情况了,一般用b就够应付大多数场景。
你要是下次再从文本里提数字,记得先想想“这个数字是不是独立的”——要是需要,就把b加上,保准不会把“100”里的10误捞出来。我朋友现在每次做文本分析,都会先问我“要不要加b”,其实不是我教得多好,是她踩过坑之后,才明白这小小的符号有多重要。
为什么[0-10]匹配不了10?
因为正则里的[]
是“字符集”,只能处理单个字符或连续的单字符范围(比如0-9)。10是两个字符,没法塞在字符集里——[0-10]
实际是0-1(0和1)加重复的0,所以只匹配0、1,和10无关。要匹配10得用|
(或者)分开,比如写^10$
。
加^和$到底有什么用?
^是“字符串开头”,$是“字符串 ”,加了这两个符号,相当于给正则画了个“圈”——要求整个字符串都符合0-10的规则,而不是“字符串里有一段符合”。比如没加的话,“10a”里的“10”会被匹配到,“ 10 ”(带空格)也会通过;加了之后,这些情况都会被拦截,确保输入的是纯数字。
JavaScript和Python里用这个正则有区别吗?
主要是API的使用细节不同:JavaScript里可以用regex.test(input.trim())
(trim掉前后空格更稳妥);Python里得用re.fullmatch(pattern, input_str.strip())
——注意别用re.search
,它会找字符串里的任意匹配(比如“01”里的“0”),容易出错。
输入带空格或换行符怎么办?
如果输入可能带空格(比如复制粘贴),可以在边界里加s
(匹配空格或制表符),比如^s0s$|^s10s$|^s[1-9]s$
;如果是多行输入(比如textarea),要把s
改成[sn]
,覆盖换行符的情况。
怎么避免匹配到像100里的10?
如果是从文本里提取数字(比如文章中的“评分10分”),要把边界符换成b
(单词边界)——它会确保数字前后不是字母、数字或下划线,比如b0b|b10b|b[1-9]b
,这样“100”里的“10”就不会被误匹配了。