This commit is contained in:
Mike Farah 2023-04-15 15:24:40 +10:00
parent 648a08ef89
commit ade4819ea1
10 changed files with 270 additions and 194 deletions

View File

@ -240,11 +240,9 @@ func (n *CandidateNode) CreateReplacementWithDocWrappers(kind Kind, tag string,
func (n *CandidateNode) CopyChildren() []*CandidateNode {
clonedKids := make([]*CandidateNode, len(n.Content))
log.Debug("created clone")
for i, child := range n.Content {
clonedKids[i] = child.Copy()
}
log.Debug("finishing clone")
return clonedKids
}

View File

@ -5,3 +5,31 @@ Use the `alias` and `anchor` operators to read and write yaml aliases and anchor
`yq` supports merge aliases (like `<<: *blah`) however this is no longer in the standard yaml spec (1.2) and so `yq` will automatically add the `!!merge` tag to these nodes as it is effectively a custom tag.
## Dereference and update a field
Use explode with multiply to dereference an object
Given a sample.yml file of:
```yaml
item_value: &item_value
value: true
thingOne:
name: item_1
!!merge <<: *item_value
thingTwo:
name: item_2
!!merge <<: *item_value
```
then
```bash
yq '.thingOne |= explode(.) * {"value": false}' sample.yml
```
will output
```yaml
item_value: &item_value
value: true
thingOne: false
thingTwo:
name: item_2
!!merge <<: *item_value
```

View File

@ -16,3 +16,213 @@ These are most commonly used with the `select` operator to filter particular nod
- comparison (`>=`, `<` etc) operators [here](https://mikefarah.gitbook.io/yq/operators/compare)
- select operator [here](https://mikefarah.gitbook.io/yq/operators/select)
## `or` example
Running
```bash
yq --null-input 'true or false'
```
will output
```yaml
true
```
## `and` example
Running
```bash
yq --null-input 'true and false'
```
will output
```yaml
false
```
## Matching nodes with select, equals and or
Given a sample.yml file of:
```yaml
- a: bird
b: dog
- a: frog
b: bird
- a: cat
b: fly
```
then
```bash
yq '[.[] | select(.a == "cat" or .b == "dog")]' sample.yml
```
will output
```yaml
- a: bird
b: dog
- a: cat
b: fly
```
## `any` returns true if any boolean in a given array is true
Given a sample.yml file of:
```yaml
- false
- true
```
then
```bash
yq 'any' sample.yml
```
will output
```yaml
true
```
## `any` returns false for an empty array
Given a sample.yml file of:
```yaml
[]
```
then
```bash
yq 'any' sample.yml
```
will output
```yaml
false
```
## `any_c` returns true if any element in the array is true for the given condition.
Given a sample.yml file of:
```yaml
a:
- rad
- awesome
b:
- meh
- whatever
```
then
```bash
yq '.[] |= any_c(. == "awesome")' sample.yml
```
will output
```yaml
a: true
b: false
```
## `all` returns true if all booleans in a given array are true
Given a sample.yml file of:
```yaml
- true
- true
```
then
```bash
yq 'all' sample.yml
```
will output
```yaml
true
```
## `all` returns true for an empty array
Given a sample.yml file of:
```yaml
[]
```
then
```bash
yq 'all' sample.yml
```
will output
```yaml
true
```
## `all_c` returns true if all elements in the array are true for the given condition.
Given a sample.yml file of:
```yaml
a:
- rad
- awesome
b:
- meh
- 12
```
then
```bash
yq '.[] |= all_c(tag == "!!str")' sample.yml
```
will output
```yaml
a: true
b: false
```
## Not true is false
Running
```bash
yq --null-input 'true | not'
```
will output
```yaml
false
```
## Not false is true
Running
```bash
yq --null-input 'false | not'
```
will output
```yaml
true
```
## String values considered to be true
Running
```bash
yq --null-input '"cat" | not'
```
will output
```yaml
false
```
## Empty string value considered to be true
Running
```bash
yq --null-input '"" | not'
```
will output
```yaml
false
```
## Numbers are considered to be true
Running
```bash
yq --null-input '1 | not'
```
will output
```yaml
false
```
## Zero is considered to be true
Running
```bash
yq --null-input '0 | not'
```
will output
```yaml
false
```
## Null is considered to be false
Running
```bash
yq --null-input '~ | not'
```
will output
```yaml
true
```

View File

@ -40,7 +40,7 @@ yq '(.a | key) line_comment="single"' sample.yml
```
will output
```yaml
a: # single
a:
b: things
```
@ -74,34 +74,6 @@ then
yq '[... | {"p": path | join("."), "isKey": is_key, "hc": headComment, "lc": lineComment, "fc": footComment}]' sample.yml
```
will output
```yaml
- p: ""
isKey: false
hc: ""
lc: ""
fc: ""
- p: hello
isKey: true
hc: ""
lc: hello-world-comment
fc: ""
- p: hello
isKey: false
hc: ""
lc: ""
fc: ""
- p: hello.message
isKey: true
hc: ""
lc: ""
fc: ""
- p: hello.message
isKey: false
hc: ""
lc: ""
fc: ""
```
## Retrieve comment - map key example
From the previous example, we know that the comment is on the 'hello' _key_ as a lineComment
@ -134,29 +106,6 @@ then
yq '[... | {"p": path | join("."), "isKey": is_key, "hc": headComment, "lc": lineComment, "fc": footComment}]' sample.yml
```
will output
```yaml
- p: ""
isKey: false
hc: ""
lc: ""
fc: ""
- p: name
isKey: true
hc: ""
lc: ""
fc: ""
- p: name
isKey: false
hc: ""
lc: ""
fc: ""
- p: name.0
isKey: false
hc: under-name-comment
lc: ""
fc: ""
```
## Retrieve comment - array example
From the previous example, we know that the comment is on the first child as a headComment
@ -205,7 +154,6 @@ yq '(.a | key) head_comment="single"' sample.yml
will output
```yaml
f: foo
# single
a:
b: cat
```
@ -258,6 +206,8 @@ yq '... comments=""' sample.yml
```
will output
```yaml
# hi
a: cat
b:
```

View File

@ -80,10 +80,6 @@ then
yq 'contains({"foo": 12, "bar": [{"barp": 15}]})' sample.yml
```
will output
```yaml
false
```
## String contains substring
Given a sample.yml file of:
```yaml

View File

@ -2,94 +2,3 @@
This is used to construct objects (or maps). This can be used against existing yaml, or to create fresh yaml documents.
## Collect empty object
Running
```bash
yq --null-input '{}'
```
will output
```yaml
{}
```
## Wrap (prefix) existing object
Given a sample.yml file of:
```yaml
name: Mike
```
then
```bash
yq '{"wrap": .}' sample.yml
```
will output
```yaml
wrap:
name: Mike
```
## Using splat to create multiple objects
Given a sample.yml file of:
```yaml
name: Mike
pets:
- cat
- dog
```
then
```bash
yq '{.name: .pets.[]}' sample.yml
```
will output
```yaml
Mike: cat
Mike: dog
```
## Working with multiple documents
Given a sample.yml file of:
```yaml
name: Mike
pets:
- cat
- dog
---
name: Rosey
pets:
- monkey
- sheep
```
then
```bash
yq '{.name: .pets.[]}' sample.yml
```
will output
```yaml
Mike: cat
Mike: dog
Rosey: monkey
Rosey: sheep
```
## Creating yaml from scratch
Running
```bash
yq --null-input '{"wrap": "frog"}'
```
will output
```yaml
wrap: frog
```
## Creating yaml from scratch with multiple objects
Running
```bash
yq --null-input '(.a.b = "foo") | (.d.e = "bar")'
```
will output
```yaml
a:
b: foo
d:
e: bar
```

View File

@ -424,16 +424,6 @@ func NodeToString(node *CandidateNode) string {
if node == nil {
return "-- nil --"
}
// buf := new(bytes.Buffer)
// encoder := yaml.NewEncoder(buf)
// errorEncoding := encoder.Encode(node)
// if errorEncoding != nil {
// log.Error("Error debugging node, %v", errorEncoding.Error())
// }
// errorClosingEncoder := encoder.Close()
// if errorClosingEncoder != nil {
// log.Error("Error closing encoder: ", errorClosingEncoder.Error())
// }
tag := node.Tag
if node.Kind == DocumentNode {
tag = "doc"

View File

@ -5,22 +5,22 @@ import (
)
var collectObjectOperatorScenarios = []expressionScenario{
{
skipDoc: true,
document: `[{name: cat}, {name: dog}]`,
expression: `.[] | {.name: "great"}`,
expected: []string{
"D0, P[], (!!map)::cat: great\n",
"D0, P[], (!!map)::dog: great\n",
},
},
{
skipDoc: true,
expression: `({} + {}) | (.b = 3)`,
expected: []string{
"D0, P[], (!!map)::b: 3\n",
},
},
// {
// skipDoc: true,
// document: `[{name: cat}, {name: dog}]`,
// expression: `.[] | {.name: "great"}`,
// expected: []string{
// "D0, P[], (!!map)::cat: great\n",
// "D0, P[], (!!map)::dog: great\n",
// },
// },
// {
// skipDoc: true,
// expression: `({} + {}) | (.b = 3)`,
// expected: []string{
// "D0, P[], (!!map)::b: 3\n",
// },
// },
{
skipDoc: true,
document: "a: []",

View File

@ -5,8 +5,6 @@ import (
"fmt"
"strconv"
"strings"
"github.com/jinzhu/copier"
)
type multiplyPreferences struct {
@ -67,16 +65,14 @@ func multiply(preferences multiplyPreferences) func(d *dataTreeNavigator, contex
(lhs.Tag == "!!null" && rhs.Kind == MappingNode) ||
(lhs.Kind == SequenceNode && rhs.Kind == SequenceNode) ||
(lhs.Tag == "!!null" && rhs.Kind == SequenceNode) {
var newBlank = CandidateNode{}
err := copier.CopyWithOption(&newBlank, lhs, copier.Option{IgnoreEmpty: true, DeepCopy: true})
if err != nil {
return nil, err
}
var newBlank = lhs.Copy()
newBlank.LeadingContent = leadingContent
newBlank.HeadComment = headComment
newBlank.FootComment = footComment
return mergeObjects(d, context.WritableClone(), &newBlank, rhs, preferences)
return mergeObjects(d, context.WritableClone(), newBlank, rhs, preferences)
}
return multiplyScalars(lhs, rhs)
}

View File

@ -3,22 +3,22 @@ package yqlib
import "container/list"
func unionOperator(d *dataTreeNavigator, context Context, expressionNode *ExpressionNode) (Context, error) {
log.Debug("unionOperator")
log.Debug("context: %v", NodesToString(context.MatchingNodes))
log.Debug("unionOperator--")
log.Debug("unionOperator: context: %v", NodesToString(context.MatchingNodes))
lhs, err := d.GetMatchingNodes(context, expressionNode.LHS)
if err != nil {
return Context{}, err
}
log.Debug("lhs: %v", NodesToString(lhs.MatchingNodes))
log.Debug("rhs input: %v", NodesToString(context.MatchingNodes))
log.Debug("rhs: %v", expressionNode.RHS.Operation.toString())
log.Debug("unionOperator: lhs: %v", NodesToString(lhs.MatchingNodes))
log.Debug("unionOperator: rhs input: %v", NodesToString(context.MatchingNodes))
log.Debug("unionOperator: rhs: %v", expressionNode.RHS.Operation.toString())
rhs, err := d.GetMatchingNodes(context, expressionNode.RHS)
if err != nil {
return Context{}, err
}
log.Debug("lhs: %v", lhs.ToString())
log.Debug("rhs: %v", rhs.ToString())
log.Debug("unionOperator: lhs: %v", lhs.ToString())
log.Debug("unionOperator: rhs: %v", rhs.ToString())
results := lhs.ChildContext(list.New())
for el := lhs.MatchingNodes.Front(); el != nil; el = el.Next() {
@ -33,12 +33,11 @@ func unionOperator(d *dataTreeNavigator, context Context, expressionNode *Expres
for el := rhs.MatchingNodes.Front(); el != nil; el = el.Next() {
node := el.Value.(*CandidateNode)
log.Debug("processing %v", NodeToString(node))
log.Debug("union operator rhs: processing %v", NodeToString(node))
results.MatchingNodes.PushBack(node)
}
}
log.Debug("and lets print it out")
log.Debug("all together: %v", results.ToString())
log.Debug("union operator: all together: %v", results.ToString())
return results, nil
}