高尔夫技巧
谁都能写出能用的正则表达式,猎手要写出能用的最短的那个。这就是正则高尔夫——用最少的字符把怪物和无辜者分开,一次学一个精简技巧,在每个棋盘上都达到或低于标准杆。
阅读规则:指南中的“写出更短正则的技巧” →
本课程建立在实战校验之上
你将学到
简写胜过字符类 字符类胜过分支 必要时才锚定 反向引用技巧
步骤 · 12
- 01字符最少者胜讲解
- 02去掉不必要的锚点狩猎
- 03\d 胜过 [0-9]狩猎
- 04. 胜过大字符类狩猎
- 05字符类胜过分支狩猎
- 06找出那一个区别狩猎
- 07用反向引用处理重复狩猎
- 08用范围,不用列表狩猎
- 09一个点,不用字符类狩猎
- 10必要时才锚定狩猎
- 11高尔夫:ab,一遍又一遍狩猎
- 12工具箱已集齐讲解
正则高尔夫:写出更短的正则
正则高尔夫是一种谜题:给你两组单词,写出最短的正则,匹配第一组的每个单词,且不匹配第二组的任何单词。这个名字来自代码高尔夫,字符数最少者胜。在 Regex Hunter 上,每个棋盘都有一个标准杆,即一个已知短答案的长度,达到或低于标准杆就能得到一颗星。
高尔夫会改变你读正则的方式。你不再描述整个单词,而是寻找把两组单词分开的那一个特征:只有目标含有的字母、共同的结尾、重复的字符。\d、\w 这样的简写、点号、字符类、{4} 这样的计数以及表示可选的 ?,都能用更短的长度表达同样的意思。
高尔夫写出的正则只保证对眼前这些单词有效。作为谜题这没问题,也是弄懂每个符号真正作用的好方法。但在生产代码中,请选择更清晰、也能处理未见过的输入的正则。
示例
抓住
- gray
- grey
放过
- green
- great
- groovy
gray|grey是 9 个字符,gr[ae]y是 7 个;在这些单词上,点号只用 4 个字符就能做到。抓住
- pin 4821
- year 1999
- ref 20261
放过
- pin 482
- 12 to 34
\d\d\d\d(8 个字符)变成\d{4}(5 个);一个简写重复到三次时,花括号计数就划算了。抓住
- jumped
- walked
- played
放过
- jumps
- walking
- player
^[a-z]+ed$描述了目标,但只有它们以d结尾,所以这里d$(2 个字符)就够了。抓住
- favorite
- favourite
放过
- favor
- favour
- fav
favourite|favorite有 18 个字符;favou?rite让u变成可选的,只要 10 个。
常见错误
- 缩短过了头。 每砍掉一个字符,都要对照所有无辜词重新检查;只要误中一个,更短的正则就不算数。
- 保留费字符的习惯。 锚点、
(?:…)和[0-9]在真实代码里很合理,但在高尔夫棋盘上,每一个都是你得给出理由的字符。 - 还没读题就动笔。 先比较两组单词;能把它们分开的特征往往在单词的开头或结尾,而不是中间。
阅读规则:指南中的“写出更短正则的技巧” →
延伸阅读:xkcd 的正则高尔夫:第 1313 期漫画背后的谜题 →