Regex101
Regex101 copied to clipboard
Golang generated code is not working as expected
Code Generator Language
Go
Code Snippet
I want to replace A(.)C
in ABC
with C${1}A
(the result should be CBA
). The current code is
package main
import (
"regexp"
"fmt"
)
func main() {
var re = regexp.MustCompile(`^A(.)C$`)
var str = []byte(`ABC`)
var substitution = []byte("C${1}A")
var i = 0
var count = 1
str = re.ReplaceAllFunc(str, func(s []byte) []byte {
if count < 0 {
return substitution
} else if i < count {
i += 1
return substitution
}
return s
})
fmt.Println(string(str))
}
which is not working.
The desired code is
package main
import (
"regexp"
"fmt"
)
func main() {
var re = regexp.MustCompile(`^A(.)C$`)
var str = []byte(`ABC`)
var substitution = []byte("C${1}A")
str = re.ReplaceAll(str, substitution)
fmt.Println(string(str))
}
Hi! Can you please elaborate on "not working"? Do you get an error/message? (I've never done anything in go)
Update: nevermind, ran in the Go Playground, output of first seems literal but have no knowledge of why. Proposed code seems to be just fine with one or more replacements within the string.
Thank you!
You can check the result (C${1}A
) in the online playground.
The code is doing "string" replacement, not "regex" one.
You can also check the code that I suggest in the same online playground.
Hmm, it looks like you've compiled a non-global regex, is that correct? In that scenario, only the first occurrence should be replaced. The first code examples (tries) to do that, while the second does not (unless I'm misinterpreting something).
Perhaps you can help correct the whole code generator for golang, if there are cases where it is incorrect? You can view the four different scenarios here:
Non-global substitution: https://regex101.com/r/rRAG2X/1/codegen?language=golang Global substitution: https://regex101.com/r/rRAG2X/2/codegen?language=golang Non-global match: https://regex101.com/r/rRAG2X/3/codegen?language=golang Global match: https://regex101.com/r/rRAG2X/4/codegen?language=golang
Thanks in advance!
You are right, the only problem is in the case of non-global substitution. Here is my proposal.
package main
import (
"fmt"
"regexp"
)
func main() {
var re = regexp.MustCompile(`A(.)C`)
var str = "ABCABC"
var substitution = `C${1}A`
var count = 1 // nagative counter is equivalent to global case (replace all)
str = re.ReplaceAllStringFunc(str, func(s string) string {
if count == 0 {
return s
}
count -= 1
return re.ReplaceAllString(s, substitution)
})
fmt.Println(string(str))
}
What I have done :
- I use
ReplaceAllStringFunc
in place ofReplaceAllFunc
so we can use strings and not[]byte
like in the other three cases. - I return
re.ReplaceAllString(s,substitution)
in place ofsubstitution
because ifsubstitution
contains group identifiers (like$1
) they must be expanded. - I use string literals (`...`) only for the regular expressions but use a regular string ("...") for the
str
variable. I think that this is something that should de corrected in all four cases (not only in the non-global replacement case). - I have simplified the code by removing the
i
variable.
You can check and play with this code in the golang playground.
I have made a proposal to manage this case easily in Go, but it was not accepted (for backward compatibility reasons). So putting the right code generator may help Go developers to write non-global replace properly.
I will try to get around to this soon.
@firasdib thanks. Here is an alternative code that introduce the missing ReplaceString
function with limiting parameter n
.
package main
import (
"fmt"
"regexp"
)
func ReplaceString(src, search, repl string, n int) string {
var re = regexp.MustCompile(search)
src = re.ReplaceAllStringFunc(src, func(s string) string {
if n == 0 {
return s
}
n -= 1
return re.ReplaceAllString(s, repl)
})
return src
}
func main() {
var re = `A(.)C`
var str = "ABCABC"
var substitution = `C${1}A`
fmt.Println(ReplaceString(str, re, substitution, 1))
}
This code in Google Playground.
You can use this one or the code from my previous comment.
Did you ever fix this @firasdib ?