ZetCode

Golang Regexp.ReplaceAllLiteral

最后修改于 2025 年 4 月 20 日

本教程讲解了如何在 Go 中使用 Regexp.ReplaceAllLiteral 方法。我们将涵盖它与 ReplaceAll 的区别,并提供实际示例。

一个 正则表达式 是一个定义搜索模式的字符序列。它用于在字符串中进行模式匹配。

Regexp.ReplaceAllLiteral 方法使用字面替换字符串替换正则表达式的匹配项。与 ReplaceAll 不同,它将替换视为字面文本,不解释 $ 符号。

基本 ReplaceAllLiteral 示例

ReplaceAllLiteral 最简单的用法是用固定字符串替换所有匹配项。这里我们将所有数字替换为“X”。

basic_replace.go
package main

import (
    "fmt"
    "regexp"
)

func main() {
    re := regexp.MustCompile(`\d`)
    text := "Order 12345 shipped on 2025-04-20"
    
    result := re.ReplaceAllLiteralString(text, "X")
    fmt.Println(result) // Order XXXXX shipped on XXXX-XX-XX
}

我们编译一个匹配任何数字的模式。ReplaceAllLiteralString 将每个数字逐字替换为“X”,没有任何特殊解释。

字面替换 vs 模板替换

此示例演示了在使用替换中的 $ReplaceAllLiteralReplaceAll 之间的区别。

literal_vs_template.go
package main

import (
    "fmt"
    "regexp"
)

func main() {
    re := regexp.MustCompile(`(\w+) (\w+)`)
    text := "John Smith"
    
    literal := re.ReplaceAllLiteralString(text, "$2 $1")
    template := re.ReplaceAllString(text, "$2 $1")
    
    fmt.Println("Literal:", literal)   // $2 $1
    fmt.Println("Template:", template) // Smith John
}

ReplaceAllLiteralString 将“$2 $1”视为字面文本,而 ReplaceAllString 则将其解释为替换模板。

转义特殊字符

当您需要插入字面特殊字符,而这些字符在替换中否则会被解释时,ReplaceAllLiteral 非常有用。

escape_special.go
package main

import (
    "fmt"
    "regexp"
)

func main() {
    re := regexp.MustCompile(`\$\d+`)
    text := "Price: $100, Discount: $20"
    
    result := re.ReplaceAllLiteralString(text, "[REDACTED]")
    fmt.Println(result) // Price: [REDACTED], Discount: [REDACTED]
}

我们匹配美元金额,但希望逐字替换它们,而不对替换字符串进行任何特殊解释。

替换为空字符串

一个常见的用例是通过替换为空字符串来删除匹配的模式。这里我们删除所有标点符号。

empty_replacement.go
package main

import (
    "fmt"
    "regexp"
)

func main() {
    re := regexp.MustCompile(`[[:punct:]]`)
    text := "Hello, World! How's it going?"
    
    result := re.ReplaceAllLiteralString(text, "")
    fmt.Println(result) // Hello World Hows it going
}

[[:punct:]] 字符类匹配所有标点符号。我们通过替换为空字符串来删除它们。

字节切片替换

ReplaceAllLiteral 也可用于字节切片,这对于某些操作可能更有效。

byte_slice.go
package main

import (
    "fmt"
    "regexp"
)

func main() {
    re := regexp.MustCompile(`\b\d+\b`)
    text := []byte("Room 101 has 2 windows and 1 door")
    
    result := re.ReplaceAllLiteral(text, []byte("N"))
    fmt.Println(string(result)) // Room N has N windows and N door
}

此示例将所有独立的数字替换为“N”。字节切片版本在处理面向字节的数据时,避免了字符串转换。

多模式替换

对于复杂的替换,您可以链接多个 ReplaceAllLiteral 调用来应用连续的转换。

multiple_replace.go
package main

import (
    "fmt"
    "regexp"
)

func main() {
    text := "Secret: ABC-123-XYZ, Code: 456-789"
    
    // First replace letter groups
    re1 := regexp.MustCompile(`[A-Z]{3}`)
    text = re1.ReplaceAllLiteralString(text, "[CODE]")
    
    // Then replace number groups
    re2 := regexp.MustCompile(`\d{3}`)
    text = re2.ReplaceAllLiteralString(text, "###")
    
    fmt.Println(text) // Secret: [CODE]-###-[CODE], Code: ###-###
}

我们首先替换 3 字母代码,然后替换 3 位数字。每次替换都逐字应用于前一个操作的结果。

性能比较

当您不需要模板处理时,ReplaceAllLiteral 可能比 ReplaceAll 稍快,因为它跳过了解释步骤。

performance.go
package main

import (
    "fmt"
    "regexp"
    "time"
)

func main() {
    re := regexp.MustCompile(`\d`)
    text := "a1b2c3d4e5f6g7h8i9j0"
    const iterations = 100000
    
    start := time.Now()
    for i := 0; i < iterations; i++ {
        re.ReplaceAllString(text, "X")
    }
    fmt.Println("ReplaceAll:", time.Since(start))
    
    start = time.Now()
    for i := 0; i < iterations; i++ {
        re.ReplaceAllLiteralString(text, "X")
    }
    fmt.Println("ReplaceAllLiteral:", time.Since(start))
}

基准测试显示,当不需要模板处理时,ReplaceAllLiteral 更快,因为它不会扫描替换中的 $

来源

Go regexp.ReplaceAllLiteral 文档

本教程通过使用正则表达式进行字面字符串替换的实际示例,讲解了 Go 中的 Regexp.ReplaceAllLiteral 方法。

作者

我叫 Jan Bodnar,是一位热情的程序员,拥有丰富的编程经验。自 2007 年以来,我一直在撰写编程文章。至今,我已撰写了 1,400 多篇文章和 8 本电子书。我在教授编程方面拥有十多年的经验。

列出所有 Go 教程