mirror of
https://gitee.com/johng/gf
synced 2026-06-06 02:25:47 +08:00
add gregex.ReplaceFuncMatch/ReplaceStringFuncMatch functions for package gregex
This commit is contained in:
@ -5,8 +5,6 @@
|
||||
// You can obtain one at https://github.com/gogf/gf.
|
||||
|
||||
// Package gregex provides high performance API for regular expression functionality.
|
||||
//
|
||||
// 正则表达式.
|
||||
package gregex
|
||||
|
||||
import (
|
||||
@ -17,22 +15,18 @@ import (
|
||||
// to match the rules of regular expression pattern.
|
||||
// And returns the copy.
|
||||
//
|
||||
// 转移正则规则字符串,例如:Quote(`[foo]`) 返回 `\[foo\]`
|
||||
// Eg: Quote(`[foo]`) returns `\[foo\]`.
|
||||
func Quote(s string) string {
|
||||
return regexp.QuoteMeta(s)
|
||||
}
|
||||
|
||||
// Validate checks whether given regular expression pattern <pattern> valid.
|
||||
//
|
||||
// 校验所给定的正则表达式是否符合规范
|
||||
func Validate(pattern string) error {
|
||||
_, err := getRegexp(pattern)
|
||||
return err
|
||||
}
|
||||
|
||||
// IsMatch checks whether given bytes <src> matches <pattern>.
|
||||
//
|
||||
// 正则表达式是否匹配
|
||||
func IsMatch(pattern string, src []byte) bool {
|
||||
if r, err := getRegexp(pattern); err == nil {
|
||||
return r.Match(src)
|
||||
@ -41,15 +35,11 @@ func IsMatch(pattern string, src []byte) bool {
|
||||
}
|
||||
|
||||
// IsMatchString checks whether given string <src> matches <pattern>.
|
||||
//
|
||||
// 判断给定的字符串<src>是否满足正则表达式<pattern>.
|
||||
func IsMatchString(pattern string, src string) bool {
|
||||
return IsMatch(pattern, []byte(src))
|
||||
}
|
||||
|
||||
// MatchString return bytes slice that matched <pattern>.
|
||||
//
|
||||
// 正则匹配,并返回匹配的列表(参数[]byte)
|
||||
func Match(pattern string, src []byte) ([][]byte, error) {
|
||||
if r, err := getRegexp(pattern); err == nil {
|
||||
return r.FindSubmatch(src), nil
|
||||
@ -59,8 +49,6 @@ func Match(pattern string, src []byte) ([][]byte, error) {
|
||||
}
|
||||
|
||||
// MatchString return strings that matched <pattern>.
|
||||
//
|
||||
// 正则匹配,并返回匹配的列表(参数[]string)
|
||||
func MatchString(pattern string, src string) ([]string, error) {
|
||||
if r, err := getRegexp(pattern); err == nil {
|
||||
return r.FindStringSubmatch(src), nil
|
||||
@ -70,8 +58,6 @@ func MatchString(pattern string, src string) ([]string, error) {
|
||||
}
|
||||
|
||||
// MatchAll return all bytes slices that matched <pattern>.
|
||||
//
|
||||
// 正则匹配,并返回所有匹配的列表(参数[]string)
|
||||
func MatchAll(pattern string, src []byte) ([][][]byte, error) {
|
||||
if r, err := getRegexp(pattern); err == nil {
|
||||
return r.FindAllSubmatch(src, -1), nil
|
||||
@ -81,8 +67,6 @@ func MatchAll(pattern string, src []byte) ([][][]byte, error) {
|
||||
}
|
||||
|
||||
// MatchAllString return all strings that matched <pattern>.
|
||||
//
|
||||
// 正则匹配,并返回所有匹配的列表(参数[][]string).
|
||||
func MatchAllString(pattern string, src string) ([][]string, error) {
|
||||
if r, err := getRegexp(pattern); err == nil {
|
||||
return r.FindAllStringSubmatch(src, -1), nil
|
||||
@ -92,8 +76,6 @@ func MatchAllString(pattern string, src string) ([][]string, error) {
|
||||
}
|
||||
|
||||
// ReplaceString replace all matched <pattern> in bytes <src> with bytes <replace>.
|
||||
//
|
||||
// 正则替换(全部替换).
|
||||
func Replace(pattern string, replace, src []byte) ([]byte, error) {
|
||||
if r, err := getRegexp(pattern); err == nil {
|
||||
return r.ReplaceAll(src, replace), nil
|
||||
@ -103,8 +85,6 @@ func Replace(pattern string, replace, src []byte) ([]byte, error) {
|
||||
}
|
||||
|
||||
// ReplaceString replace all matched <pattern> in string <src> with string <replace>.
|
||||
//
|
||||
// 正则替换(全部替换),字符串
|
||||
func ReplaceString(pattern, replace, src string) (string, error) {
|
||||
r, e := Replace(pattern, []byte(replace), []byte(src))
|
||||
return string(r), e
|
||||
@ -113,11 +93,26 @@ func ReplaceString(pattern, replace, src string) (string, error) {
|
||||
// ReplaceFunc replace all matched <pattern> in bytes <src>
|
||||
// with custom replacement function <replaceFunc>.
|
||||
func ReplaceFunc(pattern string, src []byte, replaceFunc func(b []byte) []byte) ([]byte, error) {
|
||||
if r, err := getRegexp(pattern); err == nil {
|
||||
return r.ReplaceAllFunc(src, replaceFunc), nil
|
||||
} else {
|
||||
return nil, err
|
||||
}
|
||||
if r, err := getRegexp(pattern); err == nil {
|
||||
return r.ReplaceAllFunc(src, replaceFunc), nil
|
||||
} else {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
// ReplaceFunc replace all matched <pattern> in bytes <src>
|
||||
// with custom replacement function <replaceFunc>.
|
||||
// The parameter <match> type for <replaceFunc> is [][]byte,
|
||||
// which is the result contains all sub-patterns of <pattern> using Match function.
|
||||
func ReplaceFuncMatch(pattern string, src []byte, replaceFunc func(match [][]byte) []byte) ([]byte, error) {
|
||||
if r, err := getRegexp(pattern); err == nil {
|
||||
return r.ReplaceAllFunc(src, func(bytes []byte) []byte {
|
||||
match, _ := Match(pattern, src)
|
||||
return replaceFunc(match)
|
||||
}), nil
|
||||
} else {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
// ReplaceStringFunc replace all matched <pattern> in string <src>
|
||||
@ -129,6 +124,21 @@ func ReplaceStringFunc(pattern string, src string, replaceFunc func(s string) st
|
||||
return string(bytes), err
|
||||
}
|
||||
|
||||
// ReplaceStringFuncMatch replace all matched <pattern> in string <src>
|
||||
// with custom replacement function <replaceFunc>.
|
||||
// The parameter <match> type for <replaceFunc> is []string,
|
||||
// which is the result contains all sub-patterns of <pattern> using MatchString function.
|
||||
func ReplaceStringFuncMatch(pattern string, src string, replaceFunc func(match []string) string) (string, error) {
|
||||
if r, err := getRegexp(pattern); err == nil {
|
||||
return string(r.ReplaceAllFunc([]byte(src), func(bytes []byte) []byte {
|
||||
match, _ := MatchString(pattern, src)
|
||||
return []byte(replaceFunc(match))
|
||||
})), nil
|
||||
} else {
|
||||
return "", err
|
||||
}
|
||||
}
|
||||
|
||||
// Split slices <src> into substrings separated by the expression and returns a slice of
|
||||
// the substrings between those expression matches.
|
||||
func Split(pattern string, src string) []string {
|
||||
|
||||
@ -11,13 +11,15 @@ import (
|
||||
"sync"
|
||||
)
|
||||
|
||||
// 缓存对象,主要用于缓存底层regx对象
|
||||
var (
|
||||
regexMu = sync.RWMutex{}
|
||||
regexMap = make(map[string]*regexp.Regexp)
|
||||
)
|
||||
|
||||
// 根据pattern生成对应的regexp正则对象
|
||||
// getRegexp returns *regexp.Regexp object with given <pattern>.
|
||||
// It uses cache to enhance the performance for compiling regular expression pattern,
|
||||
// which means, it will return the same *regexp.Regexp object with the same regular
|
||||
// expression pattern.
|
||||
func getRegexp(pattern string) (*regexp.Regexp, error) {
|
||||
if r := getCache(pattern); r != nil {
|
||||
return r, nil
|
||||
@ -30,7 +32,7 @@ func getRegexp(pattern string) (*regexp.Regexp, error) {
|
||||
}
|
||||
}
|
||||
|
||||
// 获得正则缓存对象
|
||||
// getCache returns *regexp.Regexp object from cache by given <pattern>, for internal usage.
|
||||
func getCache(pattern string) (regex *regexp.Regexp) {
|
||||
regexMu.RLock()
|
||||
regex = regexMap[pattern]
|
||||
@ -38,7 +40,7 @@ func getCache(pattern string) (regex *regexp.Regexp) {
|
||||
return
|
||||
}
|
||||
|
||||
// 设置正则缓存对象
|
||||
// setCache stores *regexp.Regexp object into cache, for internal usage.
|
||||
func setCache(pattern string, regex *regexp.Regexp) {
|
||||
regexMu.Lock()
|
||||
regexMap[pattern] = regex
|
||||
|
||||
@ -185,6 +185,33 @@ func Test_ReplaceFun(t *testing.T) {
|
||||
})
|
||||
}
|
||||
|
||||
func Test_ReplaceFuncMatch(t *testing.T) {
|
||||
gtest.Case(t, func() {
|
||||
s := []byte("1234567890")
|
||||
p := `(\d{3})(\d{3})(.+)`
|
||||
s0, e0 := gregex.ReplaceFuncMatch(p, s, func(match [][]byte) []byte {
|
||||
return match[0]
|
||||
})
|
||||
gtest.Assert(e0, nil)
|
||||
gtest.Assert(s0, s)
|
||||
s1, e1 := gregex.ReplaceFuncMatch(p, s, func(match [][]byte) []byte {
|
||||
return match[1]
|
||||
})
|
||||
gtest.Assert(e1, nil)
|
||||
gtest.Assert(s1, []byte("123"))
|
||||
s2, e2 := gregex.ReplaceFuncMatch(p, s, func(match [][]byte) []byte {
|
||||
return match[2]
|
||||
})
|
||||
gtest.Assert(e2, nil)
|
||||
gtest.Assert(s2, []byte("456"))
|
||||
s3, e3 := gregex.ReplaceFuncMatch(p, s, func(match [][]byte) []byte {
|
||||
return match[3]
|
||||
})
|
||||
gtest.Assert(e3, nil)
|
||||
gtest.Assert(s3, []byte("7890"))
|
||||
})
|
||||
}
|
||||
|
||||
func Test_ReplaceStringFunc(t *testing.T) {
|
||||
gtest.Case(t, func() {
|
||||
re := "a(a+b+)b"
|
||||
@ -206,6 +233,33 @@ func Test_ReplaceStringFunc(t *testing.T) {
|
||||
})
|
||||
}
|
||||
|
||||
func Test_ReplaceStringFuncMatch(t *testing.T) {
|
||||
gtest.Case(t, func() {
|
||||
s := "1234567890"
|
||||
p := `(\d{3})(\d{3})(.+)`
|
||||
s0, e0 := gregex.ReplaceStringFuncMatch(p, s, func(match []string) string {
|
||||
return match[0]
|
||||
})
|
||||
gtest.Assert(e0, nil)
|
||||
gtest.Assert(s0, s)
|
||||
s1, e1 := gregex.ReplaceStringFuncMatch(p, s, func(match []string) string {
|
||||
return match[1]
|
||||
})
|
||||
gtest.Assert(e1, nil)
|
||||
gtest.Assert(s1, "123")
|
||||
s2, e2 := gregex.ReplaceStringFuncMatch(p, s, func(match []string) string {
|
||||
return match[2]
|
||||
})
|
||||
gtest.Assert(e2, nil)
|
||||
gtest.Assert(s2, "456")
|
||||
s3, e3 := gregex.ReplaceStringFuncMatch(p, s, func(match []string) string {
|
||||
return match[3]
|
||||
})
|
||||
gtest.Assert(e3, nil)
|
||||
gtest.Assert(s3, "7890")
|
||||
})
|
||||
}
|
||||
|
||||
func Test_Split(t *testing.T) {
|
||||
gtest.Case(t, func() {
|
||||
re := "a(a+b+)b"
|
||||
|
||||
Reference in New Issue
Block a user