关于正则表达式{n}与{n,m}匹配超次数问题的技术咨询
为什么grep的{n}和{n,m}会匹配超过指定次数的内容?
这绝对是grep正则入门最容易踩的坑之一——我当初刚接触正则的时候也懵过好一阵!核心原因其实很简单:默认情况下grep做的是「部分匹配」,只要行里存在任意一段符合规则的子串,整行就会被返回,而不是要求整个行(或者目标内容)完全符合你设定的重复次数限制。
给你拆解下你遇到的情况:
- 当你跑
grep "[0-9]\{2\}" ./sample.txt时,它找的是「行里有连续2位数字的片段」——像123里的12、23都符合这个规则,所以整行就被拉出来了; - 同理,
[0-9]\{2,3\}找的是「行里有连续2-3位数字的片段」,1234里的123、234都满足这个条件,所以这行也会被命中。
怎么解决?给正则加「边界限制」就行!
如果你想要精确匹配你要的重复次数(比如只找恰好2位的数字,或者长度在2-3位之间的数字,而不是更长串里的子片段),只需要给正则加上边界锚点就行:
1. 只匹配整行就是2位数字的行
如果你的需求是整行只有2位数字,用行首尾锚点^和$:
grep "^[0-9]\{2\}$" ./sample.txt
^代表行的开头,$代表行的结尾,这样就把整行牢牢限定在恰好2位数字的范围内。
2. 匹配行里独立的2位数字(不是更长数字串的一部分)
如果是要找行里单独的2位数字(比如abc12def会被匹配,但abc123def不会),用单词边界\<和\>:
grep "\<[0-9]\{2\}\>" ./sample.txt
\<标记单词的开头,\>标记单词的结尾,这样就不会匹配123里的12这种子串了。
3. 对应{n,m}的精确匹配需求
要找长度在2-3位之间的内容,同样用边界限制:
- 整行是2-3位数字:
grep "^[0-9]\{2,3\}$" ./sample.txt
- 行里有独立的2-3位数字:
grep "\<[0-9]\{2,3\}\>" ./sample.txt
4. 替代你之前的反向grep写法
如果你的需求是「行里可以有数字,但最长的连续数字不超过3位,且至少有一段2位及以上的数字」,其实不用麻烦管道两次grep,用一个正则就能搞定(记得加-E开启扩展正则,这样大括号不用转义):
grep -E "^[^0-9]*([0-9]{2,3}[^0-9]*)*$" ./sample.txt
这个正则的意思是:整行里的数字部分只能是2-3位的片段,不会出现4位及以上的连续数字,同时保证至少有一段符合要求的数字。
内容的提问来源于stack exchange,提问作者Culip




