-2

I have a code sample,

sliceArgument := args[1] // should look like e.g. `[1:5]` or `[:5]` or `[1:]`
expression := "^\\[(?P<first>\\d*?):(?P<last>\\d*?)\\]$"
r := regexp.MustCompile(expression)
r.FindStringSubmatch(sliceArgument)
startEndArgumentList := r.SubexpNames()
if len(startEndArgumentList)  >= 2 {
    argMap[`first`] = startEndArgumentList[0]
    argMap[`last`] = startEndArgumentList[1]
}

When I pass [1:5] as args[1] - I assume that SubexpNames will give me values of two groups. Instead SubexpNames returns: '', 'first', 'last'. What is wrong here?

Rudziankoŭ
  • 10,681
  • 20
  • 92
  • 192

1 Answers1

2

Docs says that the element of this array is always an empty string.

func (*Regexp) SubexpNames

func (re *Regexp) SubexpNames() []string

SubexpNames returns the names of the parenthesized subexpressions in this Regexp. The name for the first sub-expression is names[1], so that if m is a match slice, the name for m[i] is SubexpNames()[i]. Since the Regexp as a whole cannot be named, names[0] is always the empty string. The slice should not be modified.

Take a look at the example from the docs:

func main() {
    re := regexp.MustCompile("(?P<first>[a-zA-Z]+) (?P<last>[a-zA-Z]+)")
    fmt.Println(re.MatchString("Alan Turing"))
    fmt.Printf("%q\n", re.SubexpNames())
    reversed := fmt.Sprintf("${%s} ${%s}", re.SubexpNames()[2], re.SubexpNames()[1])
    fmt.Println(reversed)
    fmt.Println(re.ReplaceAllString("Alan Turing", reversed))
}

They use re.SubexpNames()[2] and re.SubexpNames()[1] as well (not re.SubexpNames()[0]).

Also: SubexpNames returns names of the groups, not matched values. To get the values, use FindStringSubmatch, see in this answer and in its demo.

Community
  • 1
  • 1
mrzasa
  • 22,895
  • 11
  • 56
  • 94