Created
January 23, 2020 05:46
-
-
Save emidoots/14c66b88633bd52b7fa710349e4c6749 to your computer and use it in GitHub Desktop.
Go | Golang | Regex replace all byte submatches | regexp.ReplaceAllSubmatchFunc |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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