【问题标题】:How to extract different variables from a regex without compiling each expression如何在不编译每个表达式的情况下从正则表达式中提取不同的变量
【发布时间】:2021-07-30 11:02:15
【问题描述】:

我有一个表示计算机对象大小的结构。该结构的对象由用户输入的字符串值构成;例如"50KB" 将被标记为 int 值 "50" 和字符串值 "KB"。

type SizeUnit string

const (
    B  = "B"
    KB = "KB"
    MB = "MB"
    GB = "GB"
    TB = "TB"
)

type ObjectSize struct {
    NumberOfUnits int
    Unit          SizeUnit
}

func NewObjectSizeFromString(input_str string) (*ObjectSize, error)

在这个函数的主体中,我首先检查输入值是否为有效格式;即任意位数,后跟“B”、“KB”、“MB”、“GB”或“TB”中的任何一个。然后我分别提取 int 和 string 组件并返回一个指向结构的指针。

不过,为了完成这三件事,我必须编译 3 次正则表达式。 第一次检查输入字符串的格式

rg, err := regexp.Compile(`^[0-9]+B$|KB$|MB$|GB$|TB$`)

然后再次编译获取int组件:

rg, err := regexp.Compile(`^[0-9]+`)
rg.FindString(input_str)

然后再次编译以获取字符串/单位组件:

rg, err := regexp.Compile(`B$|KB$|MB$|GB$|TB$`)
rg.FindString(input_str)

有没有办法通过一次正则表达式编译从输入字符串中获取两个组件?

完整的代码可以在Go Playground找到。

我应该指出这是一个学术问题,因为我正在尝试使用 Go 的正则表达式库。对于这种简单的用例,我可能会使用一个简单的 for 循环来解析输入字符串。

【问题讨论】:

  • 使用捕获组,^([0-9]+)([KMGT]?B)$

标签: regex go


【解决方案1】:

您可以使用 regexp.FindStringSubmatch 使用单个表达式捕获这两个值:

func NewObjectSizeFromString(input_str string) (*ObjectSize, error) {
    var defaultReturn *ObjectSize = nil
    full_search_pattern := `^([0-9]+)([KMGT]?B)$`

    rg, err := regexp.Compile(full_search_pattern)
    if err != nil {
        return defaultReturn, errors.New("Could not compile search expression")
    }
    matched := rg.FindStringSubmatch(input_str)
    if matched ==  nil {
        return defaultReturn, errors.New("Not in valid format")
    }
    i, err := strconv.ParseInt(matched[1], 10, 32)
    return &ObjectSize{int(i), SizeUnit(matched[2])}, nil
}

the playground

^([0-9]+)([KMGT]?B)$ 正则表达式匹配

  • ^ - 字符串开头
  • ([0-9]+) - 第 1 组(此值将保存在 matched[1] 中):一位或多位数字
  • ([KMGT]?B) - 第 2 组(将在 matched[2] 中):可选的 KMGT 字母,然后是 B 字母
  • $ - 字符串结束。

请注意,matched[0] 将举行整场比赛。

【讨论】:

  • 感谢@Wiktor。我之前尝试过 FindStringSubmatch,但我必须承认我并不真正了解如何使用它。不幸的是,我也没有发现函数 help 具有很强的描述性。但是你的例子说得很清楚,再次感谢!
猜你喜欢
  • 2018-07-29
  • 1970-01-01
  • 2021-07-13
  • 1970-01-01
  • 2018-10-21
  • 2014-01-27
  • 2011-03-20
  • 1970-01-01
  • 2020-07-04
相关资源
最近更新 更多