mirror of
https://github.com/mikefarah/yq.git
synced 2024-12-19 20:19:04 +00:00
Added tostring #72
This commit is contained in:
parent
706424a459
commit
72a78472af
@ -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"
|
||||
```
|
||||
|
||||
|
@ -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},
|
||||
|
@ -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}
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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) {
|
||||
|
Loading…
Reference in New Issue
Block a user