forked from go-enry/go-onigmo
-
Notifications
You must be signed in to change notification settings - Fork 0
/
replace.go
90 lines (77 loc) · 3.26 KB
/
replace.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
package onigmo
// ReplaceAll returns a copy of src, replacing matches of the Regexp with the
// replacement text repl. Inside repl, $ signs are interpreted as in Expand, so
// for instance $1 represents the text of the first submatch.
func (re *Regexp) ReplaceAll(src, repl []byte) []byte {
srepl := ""
return re.replaceAll(src, func(dst []byte, match []int) []byte {
if len(srepl) != len(repl) {
srepl = string(repl)
}
return re.expand(dst, srepl, src, "", match)
})
}
// ReplaceAllFunc returns a copy of src in which all matches of the Regexp have
// been replaced by the return value of function repl applied to the matched
// byte slice. The replacement returned by repl is substituted directly, without
// using Expand.
func (re *Regexp) ReplaceAllFunc(src []byte, repl func([]byte) []byte) []byte {
return re.replaceAll(src, func(dst []byte, match []int) []byte {
return append(dst, repl(src[match[0]:match[1]])...)
})
}
// ReplaceAllString returns a copy of src, replacing matches of the Regexp with
// the replacement string repl. Inside repl, $ signs are interpreted as in
// Expand, so for instance $1 represents the text of the first submatch.
func (re *Regexp) ReplaceAllString(src, repl string) string {
return string(re.ReplaceAll([]byte(src), []byte(repl)))
}
// ReplaceAllStringFunc returns a copy of src in which all matches of the Regexp
// have been replaced by the return value of function repl applied to the
// matched substring. The replacement returned by repl is substituted directly,
// without using Expand.
func (re *Regexp) ReplaceAllStringFunc(src string, repl func(string) string) string {
b := re.replaceAll([]byte(src), func(dst []byte, match []int) []byte {
return append(dst, repl(src[match[0]:match[1]])...)
})
return string(b)
}
// ReplaceAllLiteralString returns a copy of src, replacing matches of the Regexp
// with the replacement string repl. The replacement repl is substituted directly,
// without using Expand.
func (re *Regexp) ReplaceAllLiteralString(src, repl string) string {
return string(re.replaceAll([]byte(src), func(dst []byte, match []int) []byte {
return append(dst, repl...)
}))
}
// ReplaceAllLiteral returns a copy of src, replacing matches of the Regexp
// with the replacement bytes repl. The replacement repl is substituted directly,
// without using Expand.
func (re *Regexp) ReplaceAllLiteral(src, repl []byte) []byte {
return re.replaceAll(src, func(dst []byte, match []int) []byte {
return append(dst, repl...)
})
}
func (re *Regexp) replaceAll(src []byte, repl func(dst []byte, m []int) []byte) []byte {
matches := re.findAll(src, len(src))
if len(matches) == 0 {
return src
}
lastMatchEnd := 0 // end position of the most recent match
var buf []byte
for _, a := range matches {
// Copy the unmatched characters before this match.
buf = append(buf, src[lastMatchEnd:a[0]]...)
// Now insert a copy of the replacement string, but not for a
// match of the empty string immediately after another match.
// (Otherwise, we get double replacement for patterns that
// match both empty and nonempty strings.)
if a[1] > lastMatchEnd || a[0] == 0 {
buf = repl(buf, a)
}
lastMatchEnd = a[1]
}
// Copy the unmatched characters after the last match.
buf = append(buf, src[lastMatchEnd:]...)
return buf
}