github.com/sohaha/zlsgo@v1.7.13-0.20240501141223-10dd1a906f76/zstring/regex.go (about)

     1  package zstring
     2  
     3  import (
     4  	"regexp"
     5  	"sync"
     6  	"time"
     7  )
     8  
     9  type regexMapStruct struct {
    10  	Value *regexp.Regexp
    11  	Time  int64
    12  	sync.RWMutex
    13  }
    14  
    15  var (
    16  	l                 sync.RWMutex
    17  	regexCache             = map[string]*regexMapStruct{}
    18  	regexCacheTimeout uint = 1800
    19  )
    20  
    21  func init() {
    22  	go func() {
    23  		ticker := time.NewTicker(600 * time.Second)
    24  		for range ticker.C {
    25  			clearRegexpCompile()
    26  		}
    27  	}()
    28  }
    29  
    30  // RegexMatch check for match
    31  func RegexMatch(pattern string, str string) bool {
    32  	if r, err := getRegexpCompile(pattern); err == nil {
    33  		return r.Match(String2Bytes(str))
    34  	}
    35  	return false
    36  }
    37  
    38  // RegexExtract extract matching text
    39  func RegexExtract(pattern string, str string) ([]string, error) {
    40  	r, err := getRegexpCompile(pattern)
    41  	if err == nil {
    42  		return r.FindStringSubmatch(str), nil
    43  	}
    44  	return nil, err
    45  }
    46  
    47  // RegexExtractAll extract matching all text
    48  func RegexExtractAll(pattern string, str string, count ...int) ([][]string, error) {
    49  	r, err := getRegexpCompile(pattern)
    50  	if err == nil {
    51  		n := -1
    52  		if len(count) > 0 {
    53  			n = count[0]
    54  		}
    55  		return r.FindAllStringSubmatch(str, n), nil
    56  	}
    57  	return nil, err
    58  }
    59  
    60  // RegexFind return matching position
    61  func RegexFind(pattern string, str string, count int) [][]int {
    62  	if r, err := getRegexpCompile(pattern); err == nil {
    63  		return r.FindAllIndex(String2Bytes(str), count)
    64  	}
    65  	return [][]int{}
    66  }
    67  
    68  // RegexReplace replacing matches of the Regexp
    69  func RegexReplace(pattern string, str, repl string) (string, error) {
    70  	r, err := getRegexpCompile(pattern)
    71  	if err == nil {
    72  		str = r.ReplaceAllString(str, repl)
    73  	}
    74  	return str, err
    75  }
    76  
    77  // RegexReplaceFunc replacing matches of the Regexp
    78  func RegexReplaceFunc(pattern string, str string, repl func(string) string) (string, error) {
    79  	r, err := getRegexpCompile(pattern)
    80  	if err == nil {
    81  		str = r.ReplaceAllStringFunc(str, repl)
    82  	}
    83  	return str, err
    84  }
    85  
    86  // RegexSplit split the string
    87  func RegexSplit(pattern string, str string) ([]string, error) {
    88  	r, err := getRegexpCompile(pattern)
    89  	var result []string
    90  	if err == nil {
    91  		result = r.Split(str, -1)
    92  	}
    93  	return result, err
    94  }
    95  
    96  func clearRegexpCompile() {
    97  	newRegexCache := map[string]*regexMapStruct{}
    98  	l.Lock()
    99  	defer l.Unlock()
   100  	if len(regexCache) == 0 {
   101  		return
   102  	}
   103  	now := time.Now().Unix()
   104  	for k := range regexCache {
   105  		if uint(now-regexCache[k].Time) <= regexCacheTimeout {
   106  			newRegexCache[k] = &regexMapStruct{Value: regexCache[k].Value, Time: now}
   107  		}
   108  	}
   109  	regexCache = newRegexCache
   110  }
   111  
   112  func getRegexpCompile(pattern string) (r *regexp.Regexp, err error) {
   113  	l.RLock()
   114  	var data *regexMapStruct
   115  	var ok bool
   116  	data, ok = regexCache[pattern]
   117  	l.RUnlock()
   118  	if ok {
   119  		r = data.Value
   120  		return
   121  	}
   122  	r, err = regexp.Compile(pattern)
   123  	if err != nil {
   124  		return
   125  	}
   126  	l.Lock()
   127  	regexCache[pattern] = &regexMapStruct{Value: r, Time: time.Now().Unix()}
   128  	l.Unlock()
   129  	return
   130  }