aboutsummaryrefslogtreecommitdiff
path: root/src/regexp
diff options
context:
space:
mode:
authorSylvain Zimmer <sylvain@sylvainzimmer.com>2019-07-29 03:15:36 +0200
committerDaniel Martí <mvdan@mvdan.cc>2020-04-10 09:38:07 +0000
commit782fcb44b96753e6e763be91a72bcbfc3dff7ab9 (patch)
treec02f54f631c39d6c95ea2b7133aa9db84818543e /src/regexp
parent245409ea86f20fd9f4167223c2339fb238f9e4b6 (diff)
downloadgo-782fcb44b96753e6e763be91a72bcbfc3dff7ab9.tar.gz
go-782fcb44b96753e6e763be91a72bcbfc3dff7ab9.zip
regexp: add (*Regexp).SubexpIndex
SubexpIndex returns the index of the first subexpression with the given name, or -1 if there is no subexpression with that name. Fixes #32420 Change-Id: Ie1f9d22d50fb84e18added80a9d9a9f6dca8ffc4 Reviewed-on: https://go-review.googlesource.com/c/go/+/187919 Run-TryBot: Ian Lance Taylor <iant@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Daniel Martí <mvdan@mvdan.cc>
Diffstat (limited to 'src/regexp')
-rw-r--r--src/regexp/all_test.go42
-rw-r--r--src/regexp/example_test.go13
-rw-r--r--src/regexp/regexp.go18
3 files changed, 59 insertions, 14 deletions
diff --git a/src/regexp/all_test.go b/src/regexp/all_test.go
index 626a69142f..be7a2e7111 100644
--- a/src/regexp/all_test.go
+++ b/src/regexp/all_test.go
@@ -418,24 +418,32 @@ func TestLiteralPrefix(t *testing.T) {
}
}
+type subexpIndex struct {
+ name string
+ index int
+}
+
type subexpCase struct {
- input string
- num int
- names []string
+ input string
+ num int
+ names []string
+ indices []subexpIndex
}
+var emptySubexpIndices = []subexpIndex{{"", -1}, {"missing", -1}}
+
var subexpCases = []subexpCase{
- {``, 0, nil},
- {`.*`, 0, nil},
- {`abba`, 0, nil},
- {`ab(b)a`, 1, []string{"", ""}},
- {`ab(.*)a`, 1, []string{"", ""}},
- {`(.*)ab(.*)a`, 2, []string{"", "", ""}},
- {`(.*)(ab)(.*)a`, 3, []string{"", "", "", ""}},
- {`(.*)((a)b)(.*)a`, 4, []string{"", "", "", "", ""}},
- {`(.*)(\(ab)(.*)a`, 3, []string{"", "", "", ""}},
- {`(.*)(\(a\)b)(.*)a`, 3, []string{"", "", "", ""}},
- {`(?P<foo>.*)(?P<bar>(a)b)(?P<foo>.*)a`, 4, []string{"", "foo", "bar", "", "foo"}},
+ {``, 0, nil, emptySubexpIndices},
+ {`.*`, 0, nil, emptySubexpIndices},
+ {`abba`, 0, nil, emptySubexpIndices},
+ {`ab(b)a`, 1, []string{"", ""}, emptySubexpIndices},
+ {`ab(.*)a`, 1, []string{"", ""}, emptySubexpIndices},
+ {`(.*)ab(.*)a`, 2, []string{"", "", ""}, emptySubexpIndices},
+ {`(.*)(ab)(.*)a`, 3, []string{"", "", "", ""}, emptySubexpIndices},
+ {`(.*)((a)b)(.*)a`, 4, []string{"", "", "", "", ""}, emptySubexpIndices},
+ {`(.*)(\(ab)(.*)a`, 3, []string{"", "", "", ""}, emptySubexpIndices},
+ {`(.*)(\(a\)b)(.*)a`, 3, []string{"", "", "", ""}, emptySubexpIndices},
+ {`(?P<foo>.*)(?P<bar>(a)b)(?P<foo>.*)a`, 4, []string{"", "foo", "bar", "", "foo"}, []subexpIndex{{"", -1}, {"missing", -1}, {"foo", 1}, {"bar", 2}}},
}
func TestSubexp(t *testing.T) {
@@ -458,6 +466,12 @@ func TestSubexp(t *testing.T) {
}
}
}
+ for _, subexp := range c.indices {
+ index := re.SubexpIndex(subexp.name)
+ if index != subexp.index {
+ t.Errorf("%q: SubexpIndex(%q) = %d, want %d", c.input, subexp.name, index, subexp.index)
+ }
+ }
}
}
diff --git a/src/regexp/example_test.go b/src/regexp/example_test.go
index ea35a2e591..466b38b0fa 100644
--- a/src/regexp/example_test.go
+++ b/src/regexp/example_test.go
@@ -280,6 +280,19 @@ func ExampleRegexp_SubexpNames() {
// Turing Alan
}
+func ExampleRegexp_SubexpIndex() {
+ re := regexp.MustCompile(`(?P<first>[a-zA-Z]+) (?P<last>[a-zA-Z]+)`)
+ fmt.Println(re.MatchString("Alan Turing"))
+ matches := re.FindStringSubmatch("Alan Turing")
+ lastIndex := re.SubexpIndex("last")
+ fmt.Printf("last => %d\n", lastIndex)
+ fmt.Println(matches[lastIndex])
+ // Output:
+ // true
+ // last => 2
+ // Turing
+}
+
func ExampleRegexp_Split() {
a := regexp.MustCompile(`a`)
fmt.Println(a.Split("banana", -1))
diff --git a/src/regexp/regexp.go b/src/regexp/regexp.go
index 19ca6f2223..b547a2ab97 100644
--- a/src/regexp/regexp.go
+++ b/src/regexp/regexp.go
@@ -345,6 +345,24 @@ func (re *Regexp) SubexpNames() []string {
return re.subexpNames
}
+// SubexpIndex returns the index of the first subexpression with the given name,
+// or -1 if there is no subexpression with that name.
+//
+// Note that multiple subexpressions can be written using the same name, as in
+// (?P<bob>a+)(?P<bob>b+), which declares two subexpressions named "bob".
+// In this case, SubexpIndex returns the index of the leftmost such subexpression
+// in the regular expression.
+func (re *Regexp) SubexpIndex(name string) int {
+ if name != "" {
+ for i, s := range re.subexpNames {
+ if name == s {
+ return i
+ }
+ }
+ }
+ return -1
+}
+
const endOfText rune = -1
// input abstracts different representations of the input text. It provides