高尔夫技巧

谁都能写出能用的正则表达式,猎手要写出能用的最短的那个。这就是正则高尔夫——用最少的字符把怪物和无辜者分开,一次学一个精简技巧,在每个棋盘上都达到或低于标准杆。

阅读规则:指南中的“写出更短正则的技巧” →

本课程建立在实战校验之上

你将学到

简写胜过字符类 字符类胜过分支 必要时才锚定 反向引用技巧

步骤 · 12

  1. 01字符最少者胜讲解
  2. 02去掉不必要的锚点狩猎
  3. 03\d 胜过 [0-9]狩猎
  4. 04. 胜过大字符类狩猎
  5. 05字符类胜过分支狩猎
  6. 06找出那一个区别狩猎
  7. 07用反向引用处理重复狩猎
  8. 08用范围,不用列表狩猎
  9. 09一个点,不用字符类狩猎
  10. 10必要时才锚定狩猎
  11. 11高尔夫:ab,一遍又一遍狩猎
  12. 12工具箱已集齐讲解

正则高尔夫:写出更短的正则

正则高尔夫是一种谜题:给你两组单词,写出最短的正则,匹配第一组的每个单词,且不匹配第二组的任何单词。这个名字来自代码高尔夫,字符数最少者胜。在 Regex Hunter 上,每个棋盘都有一个标准杆,即一个已知短答案的长度,达到或低于标准杆就能得到一颗星。

高尔夫会改变你读正则的方式。你不再描述整个单词,而是寻找把两组单词分开的那一个特征:只有目标含有的字母、共同的结尾、重复的字符。\d、\w 这样的简写、点号、字符类、{4} 这样的计数以及表示可选的 ?,都能用更短的长度表达同样的意思。

高尔夫写出的正则只保证对眼前这些单词有效。作为谜题这没问题,也是弄懂每个符号真正作用的好方法。但在生产代码中,请选择更清晰、也能处理未见过的输入的正则。

示例

  1. /gr.y/

    抓住

    • gray
    • grey

    放过

    • green
    • great
    • groovy

    gray|grey 是 9 个字符,gr[ae]y 是 7 个;在这些单词上,点号只用 4 个字符就能做到。

  2. /\d{4}/

    抓住

    • pin 4821
    • year 1999
    • ref 20261

    放过

    • pin 482
    • 12 to 34

    \d\d\d\d(8 个字符)变成 \d{4}(5 个);一个简写重复到三次时,花括号计数就划算了。

  3. /d$/

    抓住

    • jumped
    • walked
    • played

    放过

    • jumps
    • walking
    • player

    ^[a-z]+ed$ 描述了目标,但只有它们以 d 结尾,所以这里 d$(2 个字符)就够了。

  4. /favou?rite/

    抓住

    • favorite
    • favourite

    放过

    • favor
    • favour
    • fav

    favourite|favorite 有 18 个字符;favou?rite 让 u 变成可选的,只要 10 个。

常见错误

  • 缩短过了头。 每砍掉一个字符,都要对照所有无辜词重新检查;只要误中一个,更短的正则就不算数。
  • 保留费字符的习惯。 锚点、(?:…) 和 [0-9] 在真实代码里很合理,但在高尔夫棋盘上,每一个都是你得给出理由的字符。
  • 还没读题就动笔。 先比较两组单词;能把它们分开的特征往往在单词的开头或结尾,而不是中间。

阅读规则:指南中的“写出更短正则的技巧” →

延伸阅读:xkcd 的正则高尔夫:第 1313 期漫画背后的谜题 →

延伸阅读:正则高尔夫策略:如何打出低于标准杆的成绩 →

延伸阅读:欢迎来到 Regex Hunter,享受正则高尔夫的乐趣 →

玩今天的狩猎 →