Added tostring #72

This commit is contained in:
Mike Farah 2024-03-05 10:40:55 +11:00
parent 706424a459
commit 72a78472af
6 changed files with 314 additions and 570 deletions

View File

@ -56,330 +56,32 @@ IFS= read -rd '' output < <(cat my_file)
output=$output ./yq '.data.values = strenv(output)' first.yml
```
## To up (upper) case
Works with unicode characters
## To string
Note that you may want to force `yq` to leave scalar values wrapped by passing in `--unwrapScalar=false` or `-r=f`
Given a sample.yml file of:
```yaml
água
```
then
```bash
yq 'upcase' sample.yml
```
will output
```yaml
ÁGUA
```
## To down (lower) case
Works with unicode characters
Given a sample.yml file of:
```yaml
ÁgUA
```
then
```bash
yq 'downcase' sample.yml
```
will output
```yaml
água
```
## Join strings
Given a sample.yml file of:
```yaml
- cat
- meow
- 1
- null
- true
```
then
```bash
yq 'join("; ")' sample.yml
```
will output
```yaml
cat; meow; 1; ; true
```
## Trim strings
Given a sample.yml file of:
```yaml
- ' cat'
- 'dog '
- ' cow cow '
- horse
```
then
```bash
yq '.[] | trim' sample.yml
```
will output
```yaml
cat
dog
cow cow
horse
```
## Match string
Given a sample.yml file of:
```yaml
foo bar foo
```
then
```bash
yq 'match("foo")' sample.yml
```
will output
```yaml
string: foo
offset: 0
length: 3
captures: []
```
## Match string, case insensitive
Given a sample.yml file of:
```yaml
foo bar FOO
```
then
```bash
yq '[match("(?i)foo"; "g")]' sample.yml
```
will output
```yaml
- string: foo
offset: 0
length: 3
captures: []
- string: FOO
offset: 8
length: 3
captures: []
```
## Match with global capture group
Given a sample.yml file of:
```yaml
abc abc
```
then
```bash
yq '[match("(ab)(c)"; "g")]' sample.yml
```
will output
```yaml
- string: abc
offset: 0
length: 3
captures:
- string: ab
offset: 0
length: 2
- string: c
offset: 2
length: 1
- string: abc
offset: 4
length: 3
captures:
- string: ab
offset: 4
length: 2
- string: c
offset: 6
length: 1
```
## Match with named capture groups
Given a sample.yml file of:
```yaml
foo bar foo foo foo
```
then
```bash
yq '[match("foo (?P<bar123>bar)? foo"; "g")]' sample.yml
```
will output
```yaml
- string: foo bar foo
offset: 0
length: 11
captures:
- string: bar
offset: 4
length: 3
name: bar123
- string: foo foo
offset: 12
length: 8
captures:
- string: null
offset: -1
length: 0
name: bar123
```
## Capture named groups into a map
Given a sample.yml file of:
```yaml
xyzzy-14
```
then
```bash
yq 'capture("(?P<a>[a-z]+)-(?P<n>[0-9]+)")' sample.yml
```
will output
```yaml
a: xyzzy
n: "14"
```
## Match without global flag
Given a sample.yml file of:
```yaml
cat cat
```
then
```bash
yq 'match("cat")' sample.yml
```
will output
```yaml
string: cat
offset: 0
length: 3
captures: []
```
## Match with global flag
Given a sample.yml file of:
```yaml
cat cat
```
then
```bash
yq '[match("cat"; "g")]' sample.yml
```
will output
```yaml
- string: cat
offset: 0
length: 3
captures: []
- string: cat
offset: 4
length: 3
captures: []
```
## Test using regex
Like jq's equivalent, this works like match but only returns true/false instead of full match details
Given a sample.yml file of:
```yaml
- null
- ~
- cat
- dog
- an: object
- - array
- 2
```
then
```bash
yq '.[] | test("at")' sample.yml
yq '.[] |= to_string' sample.yml
```
will output
```yaml
true
false
```
## Substitute / Replace string
This uses Golang's regex, described [here](https://github.com/google/re2/wiki/Syntax).
Note the use of `|=` to run in context of the current string value.
Given a sample.yml file of:
```yaml
a: dogs are great
```
then
```bash
yq '.a |= sub("dogs", "cats")' sample.yml
```
will output
```yaml
a: cats are great
```
## Substitute / Replace string with regex
This uses Golang's regex, described [here](https://github.com/google/re2/wiki/Syntax).
Note the use of `|=` to run in context of the current string value.
Given a sample.yml file of:
```yaml
a: cat
b: heat
```
then
```bash
yq '.[] |= sub("(a)", "${1}r")' sample.yml
```
will output
```yaml
a: cart
b: heart
```
## Custom types: that are really strings
When custom tags are encountered, yq will try to decode the underlying type.
Given a sample.yml file of:
```yaml
a: !horse cat
b: !goat heat
```
then
```bash
yq '.[] |= sub("(a)", "${1}r")' sample.yml
```
will output
```yaml
a: !horse cart
b: !goat heart
```
## Split strings
Given a sample.yml file of:
```yaml
cat; meow; 1; ; true
```
then
```bash
yq 'split("; ")' sample.yml
```
will output
```yaml
- cat
- meow
- "1"
- ""
- "true"
```
## Split strings one match
Given a sample.yml file of:
```yaml
word
```
then
```bash
yq 'split("; ")' sample.yml
```
will output
```yaml
- word
- "null"
- "~"
- cat
- "an: object"
- "- array\n- 2"
```

View File

@ -168,6 +168,7 @@ var participleYqRules = []*participleYqRule{
{"Uppercase", `upcase|ascii_?upcase`, opTokenWithPrefs(changeCaseOpType, nil, changeCasePrefs{ToUpperCase: true}), 0},
{"Downcase", `downcase|ascii_?downcase`, opTokenWithPrefs(changeCaseOpType, nil, changeCasePrefs{ToUpperCase: false}), 0},
simpleOp("trim", trimOpType),
simpleOp("to_?string", toStringOpType),
{"HexValue", `0[xX][0-9A-Fa-f]+`, hexValue(), 0},
{"FloatValueScientific", `-?[1-9](\.\d+)?[Ee][-+]?\d+`, floatValue(), 0},

View File

@ -152,6 +152,7 @@ var testOpType = &operationType{Type: "TEST", NumArgs: 1, Precedence: 50, Handle
var splitStringOpType = &operationType{Type: "SPLIT", NumArgs: 1, Precedence: 50, Handler: splitStringOperator}
var changeCaseOpType = &operationType{Type: "CHANGE_CASE", NumArgs: 0, Precedence: 50, Handler: changeCaseOperator}
var trimOpType = &operationType{Type: "TRIM", NumArgs: 0, Precedence: 50, Handler: trimSpaceOperator}
var toStringOpType = &operationType{Type: "TO_STRING", NumArgs: 0, Precedence: 50, Handler: toStringOperator}
var loadOpType = &operationType{Type: "LOAD", NumArgs: 1, Precedence: 52, Handler: loadYamlOperator}

View File

@ -51,6 +51,7 @@ type encoderPreferences struct {
}
/* encodes object as yaml string */
var chomper = regexp.MustCompile("\n+$")
func encodeOperator(_ *dataTreeNavigator, context Context, expressionNode *ExpressionNode) (Context, error) {
preferences := expressionNode.Operation.Preferences.(encoderPreferences)
@ -58,7 +59,6 @@ func encodeOperator(_ *dataTreeNavigator, context Context, expressionNode *Expre
hasOnlyOneNewLine := regexp.MustCompile("[^\n].*\n$")
endWithNewLine := regexp.MustCompile(".*\n$")
chomper := regexp.MustCompile("\n+$")
for el := context.MatchingNodes.Front(); el != nil; el = el.Next() {
candidate := el.Value.(*CandidateNode)

View File

@ -29,6 +29,37 @@ func trimSpaceOperator(_ *dataTreeNavigator, context Context, _ *ExpressionNode)
return context.ChildContext(results), nil
}
func toStringOperator(_ *dataTreeNavigator, context Context, _ *ExpressionNode) (Context, error) {
results := list.New()
for el := context.MatchingNodes.Front(); el != nil; el = el.Next() {
node := el.Value.(*CandidateNode)
var newStringNode *CandidateNode
if node.Tag == "!!str" {
newStringNode = node.CreateReplacement(ScalarNode, "!!str", node.Value)
} else if node.Kind == ScalarNode {
newStringNode = node.CreateReplacement(ScalarNode, "!!str", node.Value)
newStringNode.Style = DoubleQuotedStyle
} else {
encoderPrefs := encoderPreferences{
format: YamlFormat,
indent: ConfiguredYamlPreferences.Indent,
}
result, err := encodeToString(node, encoderPrefs)
if err != nil {
return Context{}, err
}
result = chomper.ReplaceAllString(result, "")
newStringNode = node.CreateReplacement(ScalarNode, "!!str", result)
newStringNode.Style = DoubleQuotedStyle
}
newStringNode.Tag = "!!str"
results.PushBack(newStringNode)
}
return context.ChildContext(results), nil
}
func changeCaseOperator(_ *dataTreeNavigator, context Context, expressionNode *ExpressionNode) (Context, error) {
results := list.New()
prefs := expressionNode.Operation.Preferences.(changeCasePrefs)

View File

@ -5,268 +5,277 @@ import (
)
var stringsOperatorScenarios = []expressionScenario{
// {
// description: "To up (upper) case",
// subdescription: "Works with unicode characters",
// document: `água`,
// expression: "upcase",
// expected: []string{
// "D0, P[], (!!str)::ÁGUA\n",
// },
// },
// {
// skipDoc: true,
// document: `!camel água`,
// expression: "upcase",
// expected: []string{
// "D0, P[], (!camel)::ÁGUA\n",
// },
// },
// {
// description: "To down (lower) case",
// subdescription: "Works with unicode characters",
// document: `ÁgUA`,
// expression: "downcase",
// expected: []string{
// "D0, P[], (!!str)::água\n",
// },
// },
// {
// skipDoc: true,
// document: `!camel ÁgUA`,
// expression: "downcase",
// expected: []string{
// "D0, P[], (!camel)::água\n",
// },
// },
// {
// description: "Join strings",
// document: `[cat, meow, 1, null, true]`,
// expression: `join("; ")`,
// expected: []string{
// "D0, P[], (!!str)::cat; meow; 1; ; true\n",
// },
// },
// {
// description: "Trim strings",
// document: `[" cat", "dog ", " cow cow ", horse]`,
// expression: `.[] | trim`,
// expected: []string{
// "D0, P[0], (!!str)::cat\n",
// "D0, P[1], (!!str)::dog\n",
// "D0, P[2], (!!str)::cow cow\n",
// "D0, P[3], (!!str)::horse\n",
// },
// },
// {
// skipDoc: true,
// document: `[!horse cat, !goat meow, !frog 1, null, true]`,
// expression: `join("; ")`,
// expected: []string{
// "D0, P[], (!!str)::cat; meow; 1; ; true\n",
// },
// },
// {
// description: "Match string",
// document: `foo bar foo`,
// expression: `match("foo")`,
// expected: []string{
// "D0, P[], (!!map)::string: foo\noffset: 0\nlength: 3\ncaptures: []\n",
// },
// },
// {
// skipDoc: true,
// document: `!horse foo bar foo`,
// expression: `match("foo")`,
// expected: []string{
// "D0, P[], (!!map)::string: foo\noffset: 0\nlength: 3\ncaptures: []\n",
// },
// },
// {
// description: "Match string, case insensitive",
// document: `foo bar FOO`,
// expression: `[match("(?i)foo"; "g")]`,
// expected: []string{
// "D0, P[], (!!seq)::- string: foo\n offset: 0\n length: 3\n captures: []\n- string: FOO\n offset: 8\n length: 3\n captures: []\n",
// },
// },
// {
// description: "Match with global capture group",
// document: `abc abc`,
// expression: `[match("(ab)(c)"; "g")]`,
// expected: []string{
// "D0, P[], (!!seq)::- string: abc\n offset: 0\n length: 3\n captures:\n - string: ab\n offset: 0\n length: 2\n - string: c\n offset: 2\n length: 1\n- string: abc\n offset: 4\n length: 3\n captures:\n - string: ab\n offset: 4\n length: 2\n - string: c\n offset: 6\n length: 1\n",
// },
// },
// {
// description: "Match with named capture groups",
// document: `foo bar foo foo foo`,
// expression: `[match("foo (?P<bar123>bar)? foo"; "g")]`,
// expected: []string{
// "D0, P[], (!!seq)::- string: foo bar foo\n offset: 0\n length: 11\n captures:\n - string: bar\n offset: 4\n length: 3\n name: bar123\n- string: foo foo\n offset: 12\n length: 8\n captures:\n - string: null\n offset: -1\n length: 0\n name: bar123\n",
// },
// },
// {
// description: "Capture named groups into a map",
// document: `xyzzy-14`,
// expression: `capture("(?P<a>[a-z]+)-(?P<n>[0-9]+)")`,
// expected: []string{
// "D0, P[], (!!map)::a: xyzzy\nn: \"14\"\n",
// },
// },
// {
// skipDoc: true,
// document: `!horse xyzzy-14`,
// expression: `capture("(?P<a>[a-z]+)-(?P<n>[0-9]+)")`,
// expected: []string{
// "D0, P[], (!!map)::a: xyzzy\nn: \"14\"\n",
// },
// },
// {
// skipDoc: true,
// description: "Capture named groups into a map, with null",
// document: `xyzzy-14`,
// expression: `capture("(?P<a>[a-z]+)-(?P<n>[0-9]+)(?P<bar123>bar)?")`,
// expected: []string{
// "D0, P[], (!!map)::a: xyzzy\nn: \"14\"\nbar123: null\n",
// },
// },
// {
// description: "Match without global flag",
// document: `cat cat`,
// expression: `match("cat")`,
// expected: []string{
// "D0, P[], (!!map)::string: cat\noffset: 0\nlength: 3\ncaptures: []\n",
// },
// },
// {
// description: "Match with global flag",
// document: `cat cat`,
// expression: `[match("cat"; "g")]`,
// expected: []string{
// "D0, P[], (!!seq)::- string: cat\n offset: 0\n length: 3\n captures: []\n- string: cat\n offset: 4\n length: 3\n captures: []\n",
// },
// },
// {
// skipDoc: true,
// document: `!horse cat cat`,
// expression: `[match("cat"; "g")]`,
// expected: []string{
// "D0, P[], (!!seq)::- string: cat\n offset: 0\n length: 3\n captures: []\n- string: cat\n offset: 4\n length: 3\n captures: []\n",
// },
// },
// {
// skipDoc: true,
// description: "No match",
// document: `dog`,
// expression: `match("cat"; "g")`,
// expected: []string{},
// },
// {
// skipDoc: true,
// description: "No match",
// expression: `"dog" | match("cat", "g")`,
// expected: []string{},
// },
// {
// skipDoc: true,
// description: "No match",
// expression: `"dog" | match("cat")`,
// expected: []string{},
// },
// {
// description: "Test using regex",
// subdescription: "Like jq's equivalent, this works like match but only returns true/false instead of full match details",
// document: `["cat", "dog"]`,
// expression: `.[] | test("at")`,
// expected: []string{
// "D0, P[0], (!!bool)::true\n",
// "D0, P[1], (!!bool)::false\n",
// },
// },
// {
// skipDoc: true,
// document: `[!horse "cat", !cat "dog"]`,
// expression: `.[] | test("at")`,
// expected: []string{
// "D0, P[0], (!!bool)::true\n",
// "D0, P[1], (!!bool)::false\n",
// },
// },
// {
// skipDoc: true,
// document: `["cat*", "cat*", "cat"]`,
// expression: `.[] | test("cat\*")`,
// expected: []string{
// "D0, P[0], (!!bool)::true\n",
// "D0, P[1], (!!bool)::true\n",
// "D0, P[2], (!!bool)::false\n",
// },
// },
// {
// description: "Substitute / Replace string",
// subdescription: "This uses Golang's regex, described [here](https://github.com/google/re2/wiki/Syntax).\nNote the use of `|=` to run in context of the current string value.",
// document: `a: dogs are great`,
// expression: `.a |= sub("dogs", "cats")`,
// expected: []string{
// "D0, P[], (!!map)::a: cats are great\n",
// },
// },
// {
// description: "Substitute / Replace string with regex",
// subdescription: "This uses Golang's regex, described [here](https://github.com/google/re2/wiki/Syntax).\nNote the use of `|=` to run in context of the current string value.",
// document: "a: cat\nb: heat",
// expression: `.[] |= sub("(a)", "${1}r")`,
// expected: []string{
// "D0, P[], (!!map)::a: cart\nb: heart\n",
// },
// },
// {
// description: "Custom types: that are really strings",
// subdescription: "When custom tags are encountered, yq will try to decode the underlying type.",
// document: "a: !horse cat\nb: !goat heat",
// expression: `.[] |= sub("(a)", "${1}r")`,
// expected: []string{
// "D0, P[], (!!map)::a: !horse cart\nb: !goat heart\n",
// },
// },
// {
// description: "Split strings",
// document: `"cat; meow; 1; ; true"`,
// expression: `split("; ")`,
// expected: []string{
// "D0, P[], (!!seq)::- cat\n- meow\n- \"1\"\n- \"\"\n- \"true\"\n",
// },
// },
// {
// description: "Split strings one match",
// document: `"word"`,
// expression: `split("; ")`,
// expected: []string{
// "D0, P[], (!!seq)::- word\n",
// },
// },
// {
// skipDoc: true,
// document: `!horse "word"`,
// expression: `split("; ")`,
// expected: []string{
// "D0, P[], (!!seq)::- word\n",
// },
// },
// {
// skipDoc: true,
// document: `""`,
// expression: `split("; ")`,
// expected: []string{
// "D0, P[], (!!seq)::[]\n", // dont actually want this, just not to error
// },
// },
// {
// skipDoc: true,
// expression: `split("; ")`,
// expected: []string{},
// },
{
description: "To up (upper) case",
subdescription: "Works with unicode characters",
document: `água`,
expression: "upcase",
description: "To string",
subdescription: "Note that you may want to force `yq` to leave scalar values wrapped by passing in `--unwrapScalar=false` or `-r=f`",
document: `[1, true, null, ~, cat, {an: object}, [array, 2]]`,
expression: ".[] |= to_string",
expected: []string{
"D0, P[], (!!str)::ÁGUA\n",
"D0, P[], (!!seq)::[\"1\", \"true\", \"null\", \"~\", cat, \"{an: object}\", \"[array, 2]\"]\n",
},
},
{
skipDoc: true,
document: `!camel água`,
expression: "upcase",
expected: []string{
"D0, P[], (!camel)::ÁGUA\n",
},
},
{
description: "To down (lower) case",
subdescription: "Works with unicode characters",
document: `ÁgUA`,
expression: "downcase",
expected: []string{
"D0, P[], (!!str)::água\n",
},
},
{
skipDoc: true,
document: `!camel ÁgUA`,
expression: "downcase",
expected: []string{
"D0, P[], (!camel)::água\n",
},
},
{
description: "Join strings",
document: `[cat, meow, 1, null, true]`,
expression: `join("; ")`,
expected: []string{
"D0, P[], (!!str)::cat; meow; 1; ; true\n",
},
},
{
description: "Trim strings",
document: `[" cat", "dog ", " cow cow ", horse]`,
expression: `.[] | trim`,
expected: []string{
"D0, P[0], (!!str)::cat\n",
"D0, P[1], (!!str)::dog\n",
"D0, P[2], (!!str)::cow cow\n",
"D0, P[3], (!!str)::horse\n",
},
},
{
skipDoc: true,
document: `[!horse cat, !goat meow, !frog 1, null, true]`,
expression: `join("; ")`,
expected: []string{
"D0, P[], (!!str)::cat; meow; 1; ; true\n",
},
},
{
description: "Match string",
document: `foo bar foo`,
expression: `match("foo")`,
expected: []string{
"D0, P[], (!!map)::string: foo\noffset: 0\nlength: 3\ncaptures: []\n",
},
},
{
skipDoc: true,
document: `!horse foo bar foo`,
expression: `match("foo")`,
expected: []string{
"D0, P[], (!!map)::string: foo\noffset: 0\nlength: 3\ncaptures: []\n",
},
},
{
description: "Match string, case insensitive",
document: `foo bar FOO`,
expression: `[match("(?i)foo"; "g")]`,
expected: []string{
"D0, P[], (!!seq)::- string: foo\n offset: 0\n length: 3\n captures: []\n- string: FOO\n offset: 8\n length: 3\n captures: []\n",
},
},
{
description: "Match with global capture group",
document: `abc abc`,
expression: `[match("(ab)(c)"; "g")]`,
expected: []string{
"D0, P[], (!!seq)::- string: abc\n offset: 0\n length: 3\n captures:\n - string: ab\n offset: 0\n length: 2\n - string: c\n offset: 2\n length: 1\n- string: abc\n offset: 4\n length: 3\n captures:\n - string: ab\n offset: 4\n length: 2\n - string: c\n offset: 6\n length: 1\n",
},
},
{
description: "Match with named capture groups",
document: `foo bar foo foo foo`,
expression: `[match("foo (?P<bar123>bar)? foo"; "g")]`,
expected: []string{
"D0, P[], (!!seq)::- string: foo bar foo\n offset: 0\n length: 11\n captures:\n - string: bar\n offset: 4\n length: 3\n name: bar123\n- string: foo foo\n offset: 12\n length: 8\n captures:\n - string: null\n offset: -1\n length: 0\n name: bar123\n",
},
},
{
description: "Capture named groups into a map",
document: `xyzzy-14`,
expression: `capture("(?P<a>[a-z]+)-(?P<n>[0-9]+)")`,
expected: []string{
"D0, P[], (!!map)::a: xyzzy\nn: \"14\"\n",
},
},
{
skipDoc: true,
document: `!horse xyzzy-14`,
expression: `capture("(?P<a>[a-z]+)-(?P<n>[0-9]+)")`,
expected: []string{
"D0, P[], (!!map)::a: xyzzy\nn: \"14\"\n",
},
},
{
skipDoc: true,
description: "Capture named groups into a map, with null",
document: `xyzzy-14`,
expression: `capture("(?P<a>[a-z]+)-(?P<n>[0-9]+)(?P<bar123>bar)?")`,
expected: []string{
"D0, P[], (!!map)::a: xyzzy\nn: \"14\"\nbar123: null\n",
},
},
{
description: "Match without global flag",
document: `cat cat`,
expression: `match("cat")`,
expected: []string{
"D0, P[], (!!map)::string: cat\noffset: 0\nlength: 3\ncaptures: []\n",
},
},
{
description: "Match with global flag",
document: `cat cat`,
expression: `[match("cat"; "g")]`,
expected: []string{
"D0, P[], (!!seq)::- string: cat\n offset: 0\n length: 3\n captures: []\n- string: cat\n offset: 4\n length: 3\n captures: []\n",
},
},
{
skipDoc: true,
document: `!horse cat cat`,
expression: `[match("cat"; "g")]`,
expected: []string{
"D0, P[], (!!seq)::- string: cat\n offset: 0\n length: 3\n captures: []\n- string: cat\n offset: 4\n length: 3\n captures: []\n",
},
},
{
skipDoc: true,
description: "No match",
document: `dog`,
expression: `match("cat"; "g")`,
expected: []string{},
},
{
skipDoc: true,
description: "No match",
expression: `"dog" | match("cat", "g")`,
expected: []string{},
},
{
skipDoc: true,
description: "No match",
expression: `"dog" | match("cat")`,
expected: []string{},
},
{
description: "Test using regex",
subdescription: "Like jq's equivalent, this works like match but only returns true/false instead of full match details",
document: `["cat", "dog"]`,
expression: `.[] | test("at")`,
expected: []string{
"D0, P[0], (!!bool)::true\n",
"D0, P[1], (!!bool)::false\n",
},
},
{
skipDoc: true,
document: `[!horse "cat", !cat "dog"]`,
expression: `.[] | test("at")`,
expected: []string{
"D0, P[0], (!!bool)::true\n",
"D0, P[1], (!!bool)::false\n",
},
},
{
skipDoc: true,
document: `["cat*", "cat*", "cat"]`,
expression: `.[] | test("cat\*")`,
expected: []string{
"D0, P[0], (!!bool)::true\n",
"D0, P[1], (!!bool)::true\n",
"D0, P[2], (!!bool)::false\n",
},
},
{
description: "Substitute / Replace string",
subdescription: "This uses Golang's regex, described [here](https://github.com/google/re2/wiki/Syntax).\nNote the use of `|=` to run in context of the current string value.",
document: `a: dogs are great`,
expression: `.a |= sub("dogs", "cats")`,
expected: []string{
"D0, P[], (!!map)::a: cats are great\n",
},
},
{
description: "Substitute / Replace string with regex",
subdescription: "This uses Golang's regex, described [here](https://github.com/google/re2/wiki/Syntax).\nNote the use of `|=` to run in context of the current string value.",
document: "a: cat\nb: heat",
expression: `.[] |= sub("(a)", "${1}r")`,
expected: []string{
"D0, P[], (!!map)::a: cart\nb: heart\n",
},
},
{
description: "Custom types: that are really strings",
subdescription: "When custom tags are encountered, yq will try to decode the underlying type.",
document: "a: !horse cat\nb: !goat heat",
expression: `.[] |= sub("(a)", "${1}r")`,
expected: []string{
"D0, P[], (!!map)::a: !horse cart\nb: !goat heart\n",
},
},
{
description: "Split strings",
document: `"cat; meow; 1; ; true"`,
expression: `split("; ")`,
expected: []string{
"D0, P[], (!!seq)::- cat\n- meow\n- \"1\"\n- \"\"\n- \"true\"\n",
},
},
{
description: "Split strings one match",
document: `"word"`,
expression: `split("; ")`,
expected: []string{
"D0, P[], (!!seq)::- word\n",
},
},
{
skipDoc: true,
document: `!horse "word"`,
expression: `split("; ")`,
expected: []string{
"D0, P[], (!!seq)::- word\n",
},
},
{
skipDoc: true,
document: `""`,
expression: `split("; ")`,
expected: []string{
"D0, P[], (!!seq)::[]\n", // dont actually want this, just not to error
},
},
{
skipDoc: true,
expression: `split("; ")`,
expected: []string{},
},
}
func TestStringsOperatorScenarios(t *testing.T) {