Regular expressions - replacing occurrences in Go
The Go standard library provides several methods for matching and replacing text
with regular expressions via its regexp
package. Here’s an example that
matches and replaces all the occurrences of the string “abc” in a text with “xyz”:
package main
import (
"fmt"
"regexp"
)
func main() {
text := "abc abc abc"
regex := regexp.MustCompile("abc")
fmt.Println(regex.ReplaceAllString(text, "xyz")) // xyz xyz xyz
}
Replace one or more occurrences
While the above method works well, it doesn’t help when it is desired that not
all the matches in the source text should be replaced. The regexp.Regexp
type
does not offer a Replace
method similar to strings.Replace()
where you can
specify the exact number of matches that should be replaced, but we can still
achieve the necessary effect through the ReplaceAllStringFunc()
method as
shown below:
package main
import (
"fmt"
"regexp"
)
func main() {
text := "abc abc abc"
regex := regexp.MustCompile("abc")
counter := 0
output := regex.ReplaceAllStringFunc(text, func(value string) string {
if counter == 1 {
return value
}
counter++
return regex.ReplaceAllString(value, "xyz")
})
fmt.Println(output) // xyz abc abc
}
The ReplaceAllStringFunc()
method takes the source text
as its first
argument and a function as its second. The function is called once for each time
a match is found in the text
(3 times in this case) and its return value will
replace value
in the source string.
The counter
variable is incremented each time the function runs, so we can use
it to keep track of how many replacements have been made. If the counter
is 1,
we don’t want to make any more replacements so the value
is returned as is.
This yields the desired output as shown in the snippet. You can replace 1
with
the number of occurrences that you want replaced in the source text.
Replacing occurrences from the end of the text
The ReplaceAllStringFunc()
method is also handy if you want to start replacing
the occurrences of matched text from the end of the string instead of from the
beginning. Here’s how:
package main
import (
"fmt"
"regexp"
)
func main() {
text := "abc abc abc"
regex := regexp.MustCompile("abc")
counter := 0
matches := regex.FindAllString(text, -1)
l := len(matches) - 1
output := regex.ReplaceAllStringFunc(text, func(value string) string {
if counter >= l {
return regex.ReplaceAllString(value, "xyz")
}
counter++
return value
})
fmt.Println(output) // abc abc xyz
}
In above snippet, the FindAllString()
method is used to find all the matches
in the source text
. The desired number of replacements is subsequently
subtracted from the length of the matches and compared to counter
inside the
ReplaceAllStringFunc()
function argument. And that’s how the replacement of
occurrences is made to begin from the end of the source text.
Thanks for reading, and happy coding!