如何编写适配JS与grep、匹配3个及以上连续字母的简洁正则表达式
简洁正则实现方案
不需要深层嵌套、不需要拼接完整长序列的兼容写法是存在的,同时支持JavaScript全版本、GNU/BSD grep(使用-E扩展正则参数即可),正则内容如下:
(?:a(?=b)|b(?=c)|c(?=d)|d(?=e)|e(?=f)|f(?=g)|g(?=h)|h(?=i)|i(?=j)|j(?=k)|k(?=l)|l(?=m)|m(?=n)|n(?=o)|o(?=p)|p(?=q)|q(?=r)|r(?=s)|s(?=t)|t(?=u)|u(?=v)|v(?=w)|w(?=x)|x(?=y)|y(?=z)){2,}[a-z]
实现逻辑说明
- 核心思路是拆分校验规则:连续升序字母的本质是每两个相邻字母都满足「后一个字母是前一个的下一位」,不需要枚举所有长度≥3的完整序列。
- 非捕获组内的25个分支,每个分支对应一组相邻升序字母对:匹配当前字母的同时,用正向先行断言
(?=下一个字母)校验下一位必须是连续的后续字母,不会消耗下一位字符,供下一轮匹配校验。 - 量词
{2,}要求上述相邻对至少连续匹配2次:2次相邻对对应3个连续字母,刚好满足最低长度要求,贪婪模式下会自动匹配最长的合法连续序列。 - 最后补的
[a-z]用于匹配序列的最后一个字母——因为前面的相邻对匹配只覆盖了序列中除最后一位外的所有字符(每个分支只消耗当前位,最后一位没有后续字母,无法被相邻对分支匹配)。
测试用例校验结果
abc:成功匹配abcdef:成功匹配deflmnop:成功匹配lmnopxxxxghixxxx:成功匹配ghiab:相邻对仅能匹配1次,不满足最低长度要求,无匹配zyx:无符合升序要求的相邻字母对,无匹配q r s:字母间存在空格,相邻连续校验失败,无匹配tuwx:仅能匹配t-u1组相邻对,u后为w存在字母缺失,无匹配
使用说明
- JavaScript环境:使用时按需添加全局匹配
g、忽略大小写i修饰符即可,示例:const reg = /(?:a(?=b)|b(?=c)|c(?=d)|d(?=e)|e(?=f)|f(?=g)|g(?=h)|h(?=i)|i(?=j)|j(?=k)|k(?=l)|l(?=m)|m(?=n)|n(?=o)|o(?=p)|p(?=q)|q(?=r)|r(?=s)|s(?=t)|t(?=u)|u(?=v)|v(?=w)|w(?=x)|x(?=y)|y(?=z)){2,}[a-z]/gi; - grep环境:使用扩展正则模式、按需添加忽略大小写参数即可,示例:
grep -Ei '(?:a(?=b)|b(?=c)|c(?=d)|d(?=e)|e(?=f)|f(?=g)|g(?=h)|h(?=i)|i(?=j)|j(?=k)|k(?=l)|l(?=m)|m(?=n)|n(?=o)|o(?=p)|p(?=q)|q(?=r)|r(?=s)|s(?=t)|t(?=u)|u(?=v)|v(?=w)|w(?=x)|x(?=y)|y(?=z)){2,}[a-z]' 目标文件
注:如果使用的是极旧版本、完全不支持正向先行断言的grep(仅极少数嵌入式精简环境可能出现),没有更简洁的纯POSIX基础正则写法,只能枚举所有合法序列,但枚举时也可以用上述相邻对的思路减少嵌套层级,不需要写20余层括号。
内容的提问来源于stack exchange,提问作者Stephen Ostermiller
相关产品推荐
相关产品推荐

