I'm trying to write a regular expression that in a string representing Go code will replace the name of a type, say Bar
, with an updated name, say FooBar
, but only where it appears as the type of a field in another struct or as an array of that type. So I'd like to convert for example
type Foo struct {
Bar Bar
Baz []Bar
Bars []Bar
}
into
type Foo struct {
Bar FooBar
Baz []FooBar
Bars []FooBar
}
So far, I've managed to convert the array field types using this ReplaceAllString
:
package main
import (
"fmt"
"regexp"
)
func main() {
re := regexp.MustCompile(`(\w )(\s )\[\]Bar`)
s := `type Foo struct {
Bar Bar
Baz []Bar
Bars []Bar
}`
fmt.Println(re.ReplaceAllString(s, `$1$2[]FooBar`))
}
which produces
type Foo struct {
Bar Bar
Baz []FooBar
Bars []FooBar
}
What is missing is the replacement of Bar
as the type of the first field, also named Bar
. I've tried making the []
optional like so,
package main
import (
"fmt"
"regexp"
)
func main() {
re := regexp.MustCompile(`(\w )(\s )(\[\])?Bar`)
s := `type Foo struct {
Bar Bar
Baz []Bar
Bars []Bar
}`
fmt.Println(re.ReplaceAllString(s, `$1$2$3FooBar`))
}
but this produces an output where all of the field types are missing:
type Foo struct {
Bar
Baz
Bars
}
Can someone spot what is wrong here? (I could use a two-pass approach with two different regular expressions, but would prefer to achieve this in one go).
CodePudding user response:
It turns out the third reference needs to be ${3}
, not $3
:
package main
import (
"fmt"
"regexp"
)
func main() {
re := regexp.MustCompile(`(\w )(\s )(\[\])?Bar`)
s := `type Foo struct {
Bar Bar
Baz []Bar
Bars []Bar
}`
fmt.Println(re.ReplaceAllString(s, `$1$2${3}FooBar`))
}
which produces the desired result
type Foo struct {
Bar FooBar
Baz []FooBar
Bars []FooBar
}
CodePudding user response:
depending on your situation, gofmt
might be a better option:
> gofmt -r 'Bar -> FooBar' hello.go
package hello
type Foo struct {
FooBar FooBar
Baz []FooBar
Bars []FooBar
}