第二十七回:Go 正则表达式

破解秋香的暗号(Regex)
秋香
秋香: 9527,这是我给你的藏头诗,你能看懂里面的意思吗?
“唐突西施捧心皱,伯牙抚琴对牛弹,虎落平阳被犬欺。”
唐伯虎
唐伯虎: 嘿嘿,这难不倒我!用 正则表达式 (Regex) 一扫,什么秘密都藏不住!

🔍 第一招:对暗号 (MatchString)

最简单的用法是判断字符串是否符合某种规则(比如是不是手机号,是不是邮箱)。

package main
import (
    "fmt"
    "regexp"
)

func main() {
    // 规则:^9 开头,7 结尾,中间任意字符
    // MatchString 直接判断是否匹配
    matched, _ := regexp.MatchString("^9.*7$", "9527")
    
    if matched {
        fmt.Println("对上暗号了!是自己人!")
    }
}

📜 第二招:画符 (Compile / MustCompile)

如果暗号很复杂,或者要用很多次,最好先把它“画”(编译)出来。

func main() {
    // 匹配 "秋香" 后面跟着数字
    // MustCompile: 如果正则写错了,直接 Panic (适合全局变量)
    r := regexp.MustCompile(`秋香\d+`)
    
    fmt.Println(r.MatchString("我是秋香9527")) // true
    fmt.Println(r.MatchString("我是石榴姐"))   // false
}

🕵️‍♂️ 第三招:破译密码 (提取子串)

有时候我们不仅要知道“有没有”,还要把里面的秘密取出来。比如从诗句里提取藏头。

func main() {
    // 目标:提取 "唐"、"伯"、"虎"
    // (.) 表示一个分组,代表任意一个字符
    re := regexp.MustCompile(`(唐).*,(伯).*,(虎).*`)
    
    poem := "唐突西施捧心皱,伯牙抚琴对牛弹,虎落平阳被犬欺。"
    
    // FindStringSubmatch 返回一个数组:
    // [0]: 整个匹配到的字符串
    // [1]: 第一个括号里的内容 (唐)
    // [2]: 第二个括号里的内容 (伯)...
    matches := re.FindStringSubmatch(poem)
    
    if len(matches) > 3 {
        fmt.Printf("藏头诗解密:%s%s%s\n", matches[1], matches[2], matches[3])
        // 输出:唐伯虎
    }
}

🧹 第四招:清理门户 (ReplaceAllString)

把所有讨厌的 "蟑螂" 替换成 "小强"。

re := regexp.MustCompile(`蟑螂`)
str := "家里好多蟑螂啊,打死蟑螂!"
newStr := re.ReplaceAllString(str, "小强")
fmt.Println(newStr) // 家里好多小强啊,打死小强!

📖 秘籍:常用符咒速查

符号说明举例
.任意字符(换行除外)a.c 匹配 abc, a1c
\d数字 (0-9)\d+ 匹配 9527
\w字母、数字、下划线\w+ 匹配 user_1
^开头^Hello
$结尾World$
*0次或多次go* 匹配 g, go, goo
+1次或多次go+ 匹配 go, goo (不匹配 g)
?0次或1次https? 匹配 http, https
[]字符集合[aeiou] 匹配元音

🎯 练功房(对暗号)

匹配以 "唐" 开头,"虎" 结尾的字符串。

package main
import (
    "fmt"
    "regexp"
)

func main() {
    // 填空:写正则,^表示开头,$表示结尾,.表示任意字符,*表示任意个
    match, _ := regexp.MatchString("^唐.*虎$", "唐伯虎")
    fmt.Println(match)
}

任务: 正则表达式已经写在代码里了,观察一下 ^唐.*虎$ 是什么意思?

答案: ^唐.*虎$

解析: ^ 匹配开头,.* 匹配中间任意字符(贪婪模式),$ 匹配结尾。