#3 转载:正则表达式历史
开发者 正则表达式 2021-12-19正则表达式在我们日常的软件开发过程中被广泛使用,例如编写 Nginx 配置文件、在 Linux 与 macOS 下查找文件,然而不同软件不同操作系统对于正则的应用有着不一样的行为,主要原因是正则表达式演进过程中,出现 POSIX
与 PCRE
派系之分。
coding in a complicated world
正则表达式在我们日常的软件开发过程中被广泛使用,例如编写 Nginx 配置文件、在 Linux 与 macOS 下查找文件,然而不同软件不同操作系统对于正则的应用有着不一样的行为,主要原因是正则表达式演进过程中,出现 POSIX
与 PCRE
派系之分。
正则表达式, Regular Expression, 简写: regex, regexp, 正则。
一般用来以指定模式对字符串进行查找,替换,切割。
Linux 下, grep, find 等命令支持几种风格:
find -regextype help
# find: 未知的正则表达式类型 ‘help’;合法的类型是 ‘findutils-default’, ‘ed’, ‘emacs’, ‘gnu-awk’, ‘grep’, ‘posix-awk’, ‘awk’, ‘posix-basic’, ‘posix-egrep’, ‘egrep’, ‘posix-extended’, ‘posix-minimal-basic’, ‘sed’。
man grep | grep -E '\-regexp$'
# -E, --extended-regexp
# -G, --basic-regexp
# -P, --perl-regexp
# -w, --word-regexp
# -x, --line-regexp
因为历史原因,大体上可以分为:
我见过的编程语言中都是采用最为强大的 PCRE 风格:
regex.h
(libc)regex.h
,或者使用第三方库(如 boost), C 11 之后就内置正则支持了(std::regex
, 默认 ECMAScript 风格)| Characters / constructs | Corresponding article |
| :------------------------------------------------------------------------------------------------------------------------------------------------- | :---------------------------- | ----------------- |
| \
, .
, \cX
, \d
, \D
, \f
, \n
, \r
, \s
, \S
, \t
, \v
, \w
, \W
, \0
, \xhh
, \uhhhh
, \uhhhhh
, [\b]
| Character classes |
| ^
, $
, x(?=y)
, x(?!y)
, (?<=y)x
, (?<!y)x
, \b
, \B
| Assertions |
| (x)
, (?:x)
, (?<Name>x)
, x | y
,[xyz]
,[^xyz]
,\Number
| Groups and ranges |
| *
, +
, ?
, x{n}
, x{n,}
, x{n,m}
| Quantifiers |
| \p{UnicodeProperty}
, \P{UnicodeProperty}
| Unicode property escapes |
.
\w
, \d
, \s
, \W
, \D
, \S
[abc]
[^abc]
[a-z]
(abc)
\1
(?:abc)
(?=abc)
(?!abc)
a*
, a+
, a?
a{7,9}
, a{7}
, a{7,}
a+?
, a{2,}?
^
, $
ab|cd
or\b
, \B
wordJavaScript:
g
globali
case insensitivem
multilines
single line (dotall)u
unicodey
stickyGo:
i
m
s
U
Python:
re.A
, re.ASCII
re.I
, re.IGNORECASE
re.M
, re.MULTILINE
re.S
, re.DOTALL
re.DEBUG
re.X
, re.VERBOSE
func Compile(expr string) (*Regexp, error)
func CompilePOSIX(expr string) (*Regexp, error)
func MustCompile(str string) *Regexp
func MustCompilePOSIX(str string) *Regexp
函数名称中的 Must 表示:如果正则错误,直接 panic
func (re *Regexp) Match(b []byte) bool
func (re *Regexp) MatchReader(r io.RuneReader) bool
func (re *Regexp) MatchString(s string) bool
func (re *Regexp) Find(b []byte) []byte
func (re *Regexp) FindAll(b []byte, n int) [][]byte
func (re *Regexp) FindAllIndex(b []byte, n int) [][]int
func (re *Regexp) FindAllString(s string, n int) []string
func (re *Regexp) FindAllStringIndex(s string, n int) [][]int
func (re *Regexp) FindAllStringSubmatch(s string, n int) [][]string
func (re *Regexp) FindAllStringSubmatchIndex(s string, n int) [][]int
func (re *Regexp) FindAllSubmatch(b []byte, n int) [][][]byte
func (re *Regexp) FindAllSubmatchIndex(b []byte, n int) [][]int
func (re *Regexp) FindIndex(b []byte) (loc []int)
func (re *Regexp) FindReaderIndex(r io.RuneReader) (loc []int)
func (re *Regexp) FindReaderSubmatchIndex(r io.RuneReader) []int
func (re *Regexp) FindString(s string) string
func (re *Regexp) FindStringIndex(s string) (loc []int)
func (re *Regexp) FindStringSubmatch(s string) []string
func (re *Regexp) FindStringSubmatchIndex(s string) []int
func (re *Regexp) FindSubmatch(b []byte) [][]byte
func (re *Regexp) FindSubmatchIndex(b []byte) []int
其实好记,Find(All)?(String)?(Submatch)?(Index)?
一组合就有 16 种了,再加上两个 FindReader
方法。
func (re *Regexp) ReplaceAll(src, repl []byte) []byte
func (re *Regexp) ReplaceAllFunc(src []byte, repl func([]byte) []byte) []byte
func (re *Regexp) ReplaceAllLiteral(src, repl []byte) []byte
func (re *Regexp) ReplaceAllLiteralString(src, repl string) string
func (re *Regexp) ReplaceAllString(src, repl string) string
func (re *Regexp) ReplaceAllStringFunc(src string, repl func(string) string) string
func (re *Regexp) Copy() *Regexp // DEPRECATED
func (re *Regexp) Expand(dst []byte, template []byte, src []byte, match []int) []byte
func (re *Regexp) ExpandString(dst []byte, template string, src string, match []int) []byte
func (re *Regexp) LiteralPrefix() (prefix string, complete bool)
func (re *Regexp) Longest()
func (re *Regexp) NumSubexp() int
func (re *Regexp) Split(s string, n int) []string
func (re *Regexp) String() string
func (re *Regexp) SubexpIndex(name string) int
func (re *Regexp) SubexpNames() []string
func Match(pattern string, b []byte) (matched bool, err error)
func MatchReader(pattern string, r io.RuneReader) (matched bool, err error)
func MatchString(pattern string, s string) (matched bool, err error)
func QuoteMeta(s string) string
func main() {
text := "Hello, 2021! The year 2020 was great, but 2021 will be even better."
pattern := `\b\d{4}\b` // 匹配四个数字的单词
regex, err := regexp.Compile(pattern)
if err != nil {
fmt.Println("Error compiling regex:", err)
return
}
matches := regex.FindAllString(text, -1)
for _, match := range matches {
fmt.Println(match)
}
}
Output:
2021
2020
2021