Golang regexp.MustCompilePOSIX
最后修改于 2025 年 4 月 20 日
本教程解释了如何在 Go 中使用 regexp.MustCompilePOSIX
函数。我们将介绍 POSIX 正则表达式基础知识并提供实际示例。
一个 POSIX 正则表达式 是 IEEE 定义的标准模式匹配语法。它在某些匹配规则上与 Perl 风格的正则表达式不同。
regexp.MustCompilePOSIX
函数将 POSIX 正则表达式模式编译成可重用的 Regexp
对象。如果模式无效,它会 panic。
基本的 MustCompilePOSIX 示例
这个简单的例子演示了 POSIX 正则表达式的基本模式匹配。主要区别在于交替(alternation)的工作方式。
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 字符类语法。
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 风格正则表达式的区别。
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)。
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 单词边界匹配行为。
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)行为。
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 正则表达式匹配可能具有不同的性能特征。这个例子对这两种实现进行了基准测试。
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 正则表达式对于某些模式可能较慢。对于性能关键的代码,请始终进行基准测试。
来源
本教程通过 POSIX 正则表达式用法的实际示例,涵盖了 Go 中的 regexp.MustCompilePOSIX
函数。