From 3a74b34bf158a20c8ca46b76661ccaa1a8f199e5 Mon Sep 17 00:00:00 2001 From: max Date: Mon, 6 Jul 2026 03:55:05 +0200 Subject: [PATCH] fix(strings): ignore unnamed capture groups capture() built a map key from SubexpNames() for every submatch; unnamed groups (name "") became an empty-string key (and duplicate keys for several). jq returns only named captures. --- pkg/yqlib/operator_strings.go | 10 ++++++++-- pkg/yqlib/operator_strings_test.go | 9 +++++++++ 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/pkg/yqlib/operator_strings.go b/pkg/yqlib/operator_strings.go index 3ab79b0d..28f384b2 100644 --- a/pkg/yqlib/operator_strings.go +++ b/pkg/yqlib/operator_strings.go @@ -365,8 +365,14 @@ func capture(matchPrefs matchPreferences, regEx *regexp.Regexp, candidate *Candi _, submatches := matches[0], matches[1:] for j, submatch := range submatches { - - keyNode := createScalarNode(subNames[j+1], subNames[j+1]) + name := subNames[j+1] + // jq only returns named capture groups; unnamed groups (whose + // SubexpNames entry is "") must be skipped so they don't become + // map entries with an empty-string key. + if name == "" { + continue + } + keyNode := createScalarNode(name, name) var valueNode *CandidateNode offset := allIndices[i][2+j*2] diff --git a/pkg/yqlib/operator_strings_test.go b/pkg/yqlib/operator_strings_test.go index bbcbc483..d7fbe547 100644 --- a/pkg/yqlib/operator_strings_test.go +++ b/pkg/yqlib/operator_strings_test.go @@ -364,6 +364,15 @@ var stringsOperatorScenarios = []expressionScenario{ "D0, P[], (!!seq)::[\"1\", \"true\", \"null\", \"~\", cat, \"{an: object}\", \"[array, 2]\"]\n", }, }, + { + skipDoc: true, + description: "Capture ignores unnamed groups", + document: `foobar`, + expression: `capture("(foo)(?Pbar)")`, + expected: []string{ + "D0, P[], (!!map)::rest: bar\n", + }, + }, } func TestStringsOperatorScenarios(t *testing.T) {