ZetCode

Golang regexp.MustCompilePOSIX

最后修改于 2025 年 4 月 20 日

本教程解释了如何在 Go 中使用 regexp.MustCompilePOSIX 函数。我们将介绍 POSIX 正则表达式基础知识并提供实际示例。

一个 POSIX 正则表达式 是 IEEE 定义的标准模式匹配语法。它在某些匹配规则上与 Perl 风格的正则表达式不同。

regexp.MustCompilePOSIX 函数将 POSIX 正则表达式模式编译成可重用的 Regexp 对象。如果模式无效,它会 panic。

基本的 MustCompilePOSIX 示例

这个简单的例子演示了 POSIX 正则表达式的基本模式匹配。主要区别在于交替(alternation)的工作方式。

basic_posix.go
package main

import (
    "fmt"
    "regexp"
)

func main() {

    re := regexp.MustCompilePOSIX(`hello|forest`)
    fmt.Println(re.MatchString("hello"))  // true
    fmt.Println(re.MatchString("forest")) // true
    fmt.Println(re.MatchString("smell"))  // false
}

该模式匹配“hello”或“forest”。与 Perl 风格的正则表达式不同,POSIX 正则表达式对交替使用最长优先的匹配(longest-leftmost matching)。

POSIX 与 Perl 字符类

POSIX 正则表达式具有不同的字符类定义。这个例子展示了 POSIX 字符类语法。

posix_classes.go
package main

import (
    "fmt"
    "regexp"
)

func main() {
    re := regexp.MustCompilePOSIX(`[[:alpha:]]+`)
    inputs := []string{"hello", "123", "abc123"}

    for _, input := range inputs {
        if re.MatchString(input) {
            fmt.Printf("%q contains only letters\n", input)
        } else {
            fmt.Printf("%q doesn't contain only letters\n", input)
        }
    }
}

POSIX 使用 [[:alpha:]] 来表示字母,而不是 \p{L}。该模式匹配只包含字母字符的字符串。

POSIX 交替行为

POSIX 正则表达式对交替使用最长优先的匹配。这个例子演示了与 Perl 风格正则表达式的区别。

posix_alternation.go
package main

import (
    "fmt"
    "regexp"
)

func main() {
    posixRe := regexp.MustCompilePOSIX(`get|getter`)
    perlRe := regexp.MustCompile(`get|getter`)

    input := "getter"

    fmt.Println("POSIX match:", posixRe.FindString(input)) // getter
    fmt.Println("Perl match:", perlRe.FindString(input))   // get
}

POSIX 正则表达式匹配最长的可能的左侧备选项(“getter”),而 Perl 风格匹配第一个有效的备选项(“get”)。

POSIX 方括号表达式

POSIX 支持用于字符类的特殊方括号表达式。这个例子展示了排序符号(collating symbols)和等价类(equivalence classes)。

posix_brackets.go
package main

import (
    "fmt"
    "regexp"
)

func main() {
    // Matches 'a', 'b', or 'ch' (Spanish collation)
    re := regexp.MustCompilePOSIX(`[[.a.][.b.][.ch.]]`)
    
    inputs := []string{"a", "b", "ch", "c", "h"}

    for _, input := range inputs {
        if re.MatchString(input) {
            fmt.Printf("%q matches\n", input)
        } else {
            fmt.Printf("%q doesn't match\n", input)
        }
    }
}

该模式使用 POSIX 排序符号 [.ch.] 将“ch”在西班牙语排序顺序中视为一个单独的字符。

POSIX 单词边界

POSIX 正则表达式处理单词边界的方式不同。这个例子展示了 POSIX 单词边界匹配行为。

posix_word_boundaries.go
package main

import (
    "fmt"
    "regexp"
)

func main() {
    re := regexp.MustCompilePOSIX(`\bword\b`)
    inputs := []string{"word", "wordy", "a word", "word's"}

    for _, input := range inputs {
        if re.MatchString(input) {
            fmt.Printf("%q matches whole word\n", input)
        } else {
            fmt.Printf("%q doesn't match whole word\n", input)
        }
    }
}

POSIX 单词边界 \b 考虑的字符定义与 Perl 正则表达式不同。对于非 ASCII 字符,行为可能会有所不同。

POSIX 重复限制

POSIX 正则表达式对重复运算符有不同的规则。这个例子演示了贪婪匹配(greedy matching)行为。

posix_repetition.go
package main

import (
    "fmt"
    "regexp"
)

func main() {
    re := regexp.MustCompilePOSIX(`a{1,2}abb`)
    inputs := []string{"aabb", "aaabb", "aaaabb"}

    for _, input := range inputs {
        if re.MatchString(input) {
            fmt.Printf("%q matches\n", input)
        } else {
            fmt.Printf("%q doesn't match\n", input)
        }
    }
}

POSIX 在可能的情况下总是取最大重复次数。在这里,如果存在,a{1,2} 将匹配两个 'a'。

POSIX 与 Perl 正则表达式性能

POSIX 正则表达式匹配可能具有不同的性能特征。这个例子对这两种实现进行了基准测试。

posix_performance.go
package main

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

func main() {
    text := "a long text with many patterns to match against"
    posixRe := regexp.MustCompilePOSIX(`pattern|match|text`)
    perlRe := regexp.MustCompile(`pattern|match|text`)

    start := time.Now()
    for i := 0; i < 10000; i++ {
        posixRe.MatchString(text)
    }
    fmt.Println("POSIX time:", time.Since(start))

    start = time.Now()
    for i := 0; i < 10000; i++ {
        perlRe.MatchString(text)
    }
    fmt.Println("Perl time:", time.Since(start))
}

由于其不同的匹配算法,POSIX 正则表达式对于某些模式可能较慢。对于性能关键的代码,请始终进行基准测试。

来源

Go regexp 包文档

本教程通过 POSIX 正则表达式用法的实际示例,涵盖了 Go 中的 regexp.MustCompilePOSIX 函数。

作者

我叫 Jan Bodnar,我是一名充满激情的程序员,拥有丰富的编程经验。我从 2007 年开始撰写编程文章。到目前为止,我已撰写了 1,400 多篇文章和 8 本电子书。我在教授编程方面拥有超过十年的经验。

列出所有 Go 教程