From 573618e4cef8f25d0081fe93a93eb1f2d1f8dd41 Mon Sep 17 00:00:00 2001 From: Mike Farah Date: Wed, 7 Jul 2021 22:47:16 +1000 Subject: [PATCH] (wip) regex match op --- pkg/yqlib/doc/String Operators.md | 39 ++----------------------- pkg/yqlib/operator_strings.go | 23 +++++++++------ pkg/yqlib/operator_strings_test.go | 46 ++++++++++++++++++------------ 3 files changed, 44 insertions(+), 64 deletions(-) diff --git a/pkg/yqlib/doc/String Operators.md b/pkg/yqlib/doc/String Operators.md index f6d30637..581b2149 100644 --- a/pkg/yqlib/doc/String Operators.md +++ b/pkg/yqlib/doc/String Operators.md @@ -1,47 +1,13 @@ # String Operators -## Match string -Given a sample.yml file of: -```yaml -cat -``` -then -```bash -yq eval 'match("at")' sample.yml -``` -will output -```yaml -string: at -offset: 1 -length: 2 -captures: [] -``` - -## Match string, case insensitive -Given a sample.yml file of: -```yaml -cAt -``` -then -```bash -yq eval 'match("(?i)at")' sample.yml -``` -will output -```yaml -string: At -offset: 1 -length: 2 -captures: [] -``` - -## Match with capture groups +## Match with names capture groups Given a sample.yml file of: ```yaml a cat ``` then ```bash -yq eval 'match("c(.t)")' sample.yml +yq eval 'match("c(?P.t)")' sample.yml ``` will output ```yaml @@ -52,5 +18,6 @@ captures: - string: at offset: 3 length: 2 + name: cool ``` diff --git a/pkg/yqlib/operator_strings.go b/pkg/yqlib/operator_strings.go index e5b24cd1..911e207e 100644 --- a/pkg/yqlib/operator_strings.go +++ b/pkg/yqlib/operator_strings.go @@ -74,24 +74,29 @@ func substituteStringOperator(d *dataTreeNavigator, context Context, expressionN } -func addMatch(original []*yaml.Node, match string, offset int) []*yaml.Node { - return append(original, +func addMatch(original []*yaml.Node, match string, offset int, name string) []*yaml.Node { + newContent := append(original, createScalarNode("string", "string"), createScalarNode(match, match), createScalarNode("offset", "offset"), createScalarNode(offset, fmt.Sprintf("%v", offset)), createScalarNode("length", "length"), createScalarNode(len(match), fmt.Sprintf("%v", len(match)))) + + if name != "" { + newContent = append(newContent, + createScalarNode("name", "name"), + createScalarNode(name, name), + ) + } + return newContent } func match(regEx *regexp.Regexp, candidate *CandidateNode, value string, results *list.List) { - // captures = FindAllStringSubmatch - // FindAllStringSubmatchIndex = offset? - //string array - // subNames := regEx.SubexpNames() + subNames := regEx.SubexpNames() + log.Debugf("subNames %v", subNames) - //array of arrays allMatches := regEx.FindAllStringSubmatch(value, -1) allIndices := regEx.FindAllStringSubmatchIndex(value, -1) @@ -100,12 +105,12 @@ func match(regEx *regexp.Regexp, candidate *CandidateNode, value string, results match, submatches := matches[0], matches[1:] for j, submatch := range submatches { captureNode := &yaml.Node{Kind: yaml.MappingNode} - captureNode.Content = addMatch(capturesNode.Content, submatch, allIndices[i][2+j*2]) + captureNode.Content = addMatch(capturesNode.Content, submatch, allIndices[i][2+j*2], subNames[j+1]) capturesNode.Content = append(capturesNode.Content, captureNode) } node := &yaml.Node{Kind: yaml.MappingNode} - node.Content = addMatch(node.Content, match, allIndices[i][0]) + node.Content = addMatch(node.Content, match, allIndices[i][0], "") node.Content = append(node.Content, createScalarNode("captures", "captures"), capturesNode, diff --git a/pkg/yqlib/operator_strings_test.go b/pkg/yqlib/operator_strings_test.go index 3bd3b43b..655dc2ec 100644 --- a/pkg/yqlib/operator_strings_test.go +++ b/pkg/yqlib/operator_strings_test.go @@ -13,28 +13,36 @@ var stringsOperatorScenarios = []expressionScenario{ // "D0, P[], (!!str)::cat; meow; 1; ; true\n", // }, // }, + // { + // description: "Match string", + // document: `cat`, + // expression: `match("at")`, + // expected: []string{ + // "D0, P[], ()::string: at\noffset: 1\nlength: 2\ncaptures: []\n", + // }, + // }, + // { + // description: "Match string, case insensitive", + // document: `cAt`, + // expression: `match("(?i)at")`, + // expected: []string{ + // "D0, P[], ()::string: At\noffset: 1\nlength: 2\ncaptures: []\n", + // }, + // }, + // { + // description: "Match with capture groups", + // document: `a cat`, + // expression: `match("c(.t)")`, + // expected: []string{ + // "D0, P[], ()::string: cat\noffset: 2\nlength: 3\ncaptures:\n - string: at\n offset: 3\n length: 2\n", + // }, + // }, { - description: "Match string", - document: `cat`, - expression: `match("at")`, - expected: []string{ - "D0, P[], ()::string: at\noffset: 1\nlength: 2\ncaptures: []\n", - }, - }, - { - description: "Match string, case insensitive", - document: `cAt`, - expression: `match("(?i)at")`, - expected: []string{ - "D0, P[], ()::string: At\noffset: 1\nlength: 2\ncaptures: []\n", - }, - }, - { - description: "Match with capture groups", + description: "Match with names capture groups", document: `a cat`, - expression: `match("c(.t)")`, + expression: `match("c(?P.t)")`, expected: []string{ - "D0, P[], ()::string: cat\noffset: 2\nlength: 3\ncaptures:\n - string: at\n offset: 3\n length: 2\n", + "D0, P[], ()::string: cat\noffset: 2\nlength: 3\ncaptures:\n - string: at\n offset: 3\n length: 2\n name: cool\n", }, }, // {