Skip to content

Instantly share code, notes, and snippets.

@slimsag
Created January 23, 2020 05:46
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save slimsag/14c66b88633bd52b7fa710349e4c6749 to your computer and use it in GitHub Desktop.
Save slimsag/14c66b88633bd52b7fa710349e4c6749 to your computer and use it in GitHub Desktop.
Go | Golang | Regex replace all byte submatches | regexp.ReplaceAllSubmatchFunc |
// replaceAllSubmatchFunc is the missing regexp.ReplaceAllSubmatchFunc; to use it:
//
// pattern := regexp.MustCompile(...)
// data = replaceAllSubmatchFunc(pattern, data, func(groups [][]byte) [][]byte {
// // mutate groups here
// return groups
// })
//
// This snippet is MIT licensed. Please cite by leaving this comment in place. Find
// the latest version at:
//
// https://gist.github.com/slimsag/14c66b88633bd52b7fa710349e4c6749
//
func replaceAllSubmatchFunc(re *regexp.Regexp, src []byte, repl func([][]byte) [][]byte, n int) []byte {
var (
result = make([]byte, 0, len(src))
matches = re.FindAllSubmatchIndex(src, n)
last = 0
)
for _, match := range matches {
// Append bytes between our last match and this one (i.e. non-matched bytes).
matchStart := match[0]
matchEnd := match[1]
result = append(result, src[last:matchStart]...)
last = matchEnd
// Determine the groups / submatch bytes and indices.
groups := [][]byte{}
groupIndices := [][2]int{}
for i := 2; i < len(match); i += 2 {
start := match[i]
end := match[i+1]
groups = append(groups, src[start:end])
groupIndices = append(groupIndices, [2]int{start, end})
}
// Replace the groups as desired.
groups = repl(groups)
// Append match data.
lastGroup := matchStart
for i, newValue := range groups {
// Append bytes between our last group match and this one (i.e. non-group-matched bytes)
groupStart := groupIndices[i][0]
groupEnd := groupIndices[i][1]
result = append(result, src[lastGroup:groupStart]...)
lastGroup = groupEnd
// Append the new group value.
result = append(result, newValue...)
}
result = append(result, src[lastGroup:matchEnd]...) // remaining
}
result = append(result, src[last:]...) // remaining
return result
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment