在Go中捕获可选存在的组的正则表达式。

huangapple go评论82阅读模式
英文:

Regular expression to capture a group that is optionally present in Go

问题

我正在尝试编写一个正则表达式,用于在表示Go代码的字符串中将类型名称(例如Bar)替换为更新后的名称(例如FooBar),但仅在它作为另一个结构体字段的类型或该类型的数组时才替换。因此,我想将以下代码:

type Foo struct {
    Bar  Bar
    Baz  []Bar
    Bars []Bar
}

转换为:

type Foo struct {
    Bar  FooBar
    Baz  []FooBar
    Bars []FooBar
}

到目前为止,我已经成功使用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`))
}

这将产生以下输出:

type Foo struct {
    Bar  Bar
    Baz  []FooBar
    Bars []FooBar
}

但是,缺少将Bar替换为FooBar的第一个字段的类型。我尝试将[]设为可选项,如下所示:

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`))
}

但是,这会导致所有字段类型都丢失的输出:

type Foo struct {
    Bar
    Baz
    Bars
}

这里出了什么问题?(我可以使用两个不同的正则表达式进行两次处理,但我更希望一次完成)。

英文:

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
}

The replacement of Bar is missing 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
}

What is wrong here? (I could use a two-pass approach with two different regular expressions, but I would prefer to achieve this in one go).

答案1

得分: 2

根据你的情况,gofmt可能是一个更好的选择:

gofmt -r 'Bar -> FooBar' hello.go
package hello

type Foo struct {
        FooBar FooBar
        Baz    []FooBar
        Bars   []FooBar
}

https://godocs.io/cmd/gofmt

英文:

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
}

https://godocs.io/cmd/gofmt

答案2

得分: 1

原文翻译如下:

原来第三个引用需要${3},而不是$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$2FooBar`))
}

这将产生期望的结果

type Foo struct {
	Bar  FooBar
	Baz  []FooBar
	Bars []FooBar
}
英文:

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$2FooBar`))
}

which produces the desired result

type Foo struct {
	Bar  FooBar
	Baz  []FooBar
	Bars []FooBar
}

huangapple
  • 本文由 发表于 2023年1月15日 00:15:02
  • 转载请务必保留本文链接:https://go.coder-hub.com/75119361.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定