ZetCode

Golang regexp.QuoteMeta

最后修改于 2025 年 4 月 20 日

本教程解释了如何在Go中使用regexp.QuoteMeta函数。我们将介绍它的用途,并提供转义正则表达式元字符的实际示例。

一个正则表达式是定义搜索模式的字符序列。像.*+这样的特殊字符在正则表达式模式中具有特殊含义。

regexp.QuoteMeta函数会转义字符串中的所有正则表达式元字符。返回的字符串是一个匹配文字文本的正则表达式。

基本的regexp.QuoteMeta示例

regexp.QuoteMeta最简单的用法是转义包含正则表达式元字符的字符串。这使得它们能够被字面匹配。

basic_quote.go
package main

import (
    "fmt"
    "regexp"
)

func main() {
    str := `Hello. there!*`
    quoted := regexp.QuoteMeta(str)

    fmt.Println("Original:", str)
    fmt.Println("Quoted:", quoted)

    re := regexp.MustCompile(quoted)
    fmt.Println("Match:", re.MatchString("Hello. there!*"))
}

该函数转义了.*字符。编译后的正则表达式将匹配字面字符串 "Hello. there!*"。

转义用户输入

从用户输入构建正则表达式模式时,请务必使用QuoteMeta。这可以防止正则表达式注入攻击。

user_input.go
package main

import (
    "fmt"
    "regexp"
)

func main() {
    userInput := `file*.txt`
    safePattern := regexp.QuoteMeta(userInput) + `$`
    
    re := regexp.MustCompile(safePattern)
    
    fmt.Println("Match file.txt:", re.MatchString("file.txt"))
    fmt.Println("Match file1.txt:", re.MatchString("file1.txt"))
    fmt.Println("Match file*.txt:", re.MatchString("file*.txt"))
}

不加引用时,该模式将匹配任何以".txt"结尾的文件。加引用后,它只匹配字面字符串 "file*.txt"。

转义路径分隔符

文件路径通常包含正则表达式元字符。此示例显示了如何安全地匹配路径。

path_escape.go
package main

import (
    "fmt"
    "regexp"
)

func main() {
    path := `/usr/local/bin/go`
    quotedPath := regexp.QuoteMeta(path)
    
    re := regexp.MustCompile(quotedPath)
    
    fmt.Println("Match exact path:", re.MatchString(path))
    fmt.Println("Match similar path:", re.MatchString("/usr/local/bin/golang"))
}

正斜杠被转义,确保正则表达式匹配确切的路径字符串。如果不加引用,斜杠将被解释为正则表达式分隔符。

与其他模式结合使用

QuoteMeta可以与其他正则表达式模式结合使用。这里我们创建一个匹配字面前缀的模式。

combined_pattern.go
package main

import (
    "fmt"
    "regexp"
)

func main() {
    prefix := `user[input]`
    suffix := `_\d+`
    
    pattern := regexp.QuoteMeta(prefix) + suffix
    re := regexp.MustCompile(pattern)
    
    tests := []string{
        "user[input]_123",
        "user_input_456",
        "user[input]X789",
    }
    
    for _, test := range tests {
        fmt.Printf("%s: %t\n", test, re.MatchString(test))
    }
}

前缀中的方括号被转义,而后缀使用正则表达式元字符。只有同时匹配这两个部分的字符串才会被匹配。

为替换字符串转义

在使用正则表达式替换时,QuoteMeta可确保字面替换。此示例演示了安全的字符串替换。

replacement.go
package main

import (
    "fmt"
    "regexp"
)

func main() {
    text := "Replace $10 with $$10"
    pattern := `\$\d+`
    replacement := regexp.QuoteMeta("$$20")
    
    re := regexp.MustCompile(pattern)
    result := re.ReplaceAllString(text, replacement)
    
    fmt.Println("Original:", text)
    fmt.Println("Replaced:", result)
}

替换字符串包含一个美元符号,该符号通常具有特殊含义。转义可确保它被视为字面美元符号。

性能比较

此示例比较了使用和不使用QuoteMeta进行匹配,以显示正确转义的重要性。

performance.go
package main

import (
    "fmt"
    "regexp"
)

func main() {
    search := `file[1].txt`
    
    // Unsafe match (might not work as expected)
    unsafeRe := regexp.MustCompile(search)
    fmt.Println("Unsafe match:", unsafeRe.MatchString(search))
    
    // Safe match with QuoteMeta
    safeRe := regexp.MustCompile(regexp.QuoteMeta(search))
    fmt.Println("Safe match:", safeRe.MatchString(search))
    
    // What happens with special characters
    testInput := "file1txt"
    fmt.Println("Unsafe match wrong input:", unsafeRe.MatchString(testInput))
    fmt.Println("Safe match wrong input:", safeRe.MatchString(testInput))
}

未加引用的模式会匹配意外的输入,因为方括号是正则表达式元字符。加引用的模式仅匹配确切的字面字符串。

转义复杂字符串

此示例显示了QuoteMeta如何处理包含多个特殊字符的字符串。

complex_escape.go
package main

import (
    "fmt"
    "regexp"
)

func main() {
    complexStr := `^$.*+?()|[]{}-\`
    quoted := regexp.QuoteMeta(complexStr)
    
    fmt.Println("Original:", complexStr)
    fmt.Println("Quoted:", quoted)
    
    re := regexp.MustCompile(quoted)
    fmt.Println("Match original:", re.MatchString(complexStr))
    fmt.Println("Match modified:", re.MatchString("^$X.*+?()|[]{}-\\"))
}

所有特殊的正则表达式元字符都已正确转义。编译后的模式将只匹配包含所有特殊字符的原始字符串。

来源

Go regexp.QuoteMeta文档

本教程通过转义字符串中的正则表达式元字符的实际示例,介绍了Go中的regexp.QuoteMeta函数。

作者

我叫Jan Bodnar,我是一名热情的程序员,拥有丰富的编程经验。我自2007年以来一直撰写编程文章。到目前为止,我已撰写了1400多篇文章和8本电子书。我在教授编程方面拥有超过十年的经验。

列出所有 Go 教程