mirror of
https://github.com/mikefarah/yq.git
synced 2024-12-19 20:19:04 +00:00
Merge branch 'subtract'
This commit is contained in:
commit
084a0f6f1e
@ -1,4 +1,43 @@
|
||||
|
||||
## Array subtraction
|
||||
Running
|
||||
```bash
|
||||
yq eval --null-input '[1,2] - [2,3]'
|
||||
```
|
||||
will output
|
||||
```yaml
|
||||
- 1
|
||||
```
|
||||
|
||||
## Array subtraction with nested array
|
||||
Running
|
||||
```bash
|
||||
yq eval --null-input '[[1], 1, 2] - [[1], 3]'
|
||||
```
|
||||
will output
|
||||
```yaml
|
||||
- 1
|
||||
- 2
|
||||
```
|
||||
|
||||
## Array subtraction with nested object
|
||||
Note that order of the keys does not matter
|
||||
|
||||
Given a sample.yml file of:
|
||||
```yaml
|
||||
- a: b
|
||||
c: d
|
||||
- a: b
|
||||
```
|
||||
then
|
||||
```bash
|
||||
yq eval '. - [{"c": "d", "a": "b"}]' sample.yml
|
||||
```
|
||||
will output
|
||||
```yaml
|
||||
- a: b
|
||||
```
|
||||
|
||||
## Number subtraction - float
|
||||
If the lhs or rhs are floats then the expression will be calculated with floats.
|
||||
|
||||
|
@ -121,6 +121,64 @@ type Operation struct {
|
||||
UpdateAssign bool // used for assign ops, when true it means we evaluate the rhs given the lhs
|
||||
}
|
||||
|
||||
func recurseNodeArrayEqual(lhs *yaml.Node, rhs *yaml.Node) bool {
|
||||
if len(lhs.Content) != len(rhs.Content) {
|
||||
return false
|
||||
}
|
||||
|
||||
for index := 0; index < len(lhs.Content); index = index + 1 {
|
||||
if !recursiveNodeEqual(lhs.Content[index], rhs.Content[index]) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func findInArray(array *yaml.Node, item *yaml.Node) int {
|
||||
|
||||
for index := 0; index < len(array.Content); index = index + 1 {
|
||||
if recursiveNodeEqual(array.Content[index], item) {
|
||||
return index
|
||||
}
|
||||
}
|
||||
return -1
|
||||
}
|
||||
|
||||
func recurseNodeObjectEqual(lhs *yaml.Node, rhs *yaml.Node) bool {
|
||||
if len(lhs.Content) != len(rhs.Content) {
|
||||
return false
|
||||
}
|
||||
|
||||
for index := 0; index < len(lhs.Content); index = index + 2 {
|
||||
key := lhs.Content[index]
|
||||
value := lhs.Content[index+1]
|
||||
|
||||
indexInRhs := findInArray(rhs, key)
|
||||
|
||||
if indexInRhs == -1 || !recursiveNodeEqual(value, rhs.Content[indexInRhs+1]) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func recursiveNodeEqual(lhs *yaml.Node, rhs *yaml.Node) bool {
|
||||
if lhs.Kind != rhs.Kind || lhs.Tag != rhs.Tag {
|
||||
return false
|
||||
} else if lhs.Tag == "!!null" {
|
||||
return true
|
||||
|
||||
} else if lhs.Kind == yaml.ScalarNode {
|
||||
return lhs.Value == rhs.Value
|
||||
} else if lhs.Kind == yaml.SequenceNode {
|
||||
return recurseNodeArrayEqual(lhs, rhs)
|
||||
} else if lhs.Kind == yaml.MappingNode {
|
||||
return recurseNodeObjectEqual(lhs, rhs)
|
||||
}
|
||||
return false
|
||||
|
||||
}
|
||||
|
||||
// yaml numbers can be hex encoded...
|
||||
func parseInt(numberString string) (string, int64, error) {
|
||||
if strings.HasPrefix(numberString, "0x") ||
|
||||
|
@ -5,7 +5,7 @@ import (
|
||||
|
||||
"strconv"
|
||||
|
||||
yaml "gopkg.in/yaml.v3"
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
func createSubtractOp(lhs *ExpressionNode, rhs *ExpressionNode) *ExpressionNode {
|
||||
@ -24,6 +24,24 @@ func subtractOperator(d *dataTreeNavigator, context Context, expressionNode *Exp
|
||||
return crossFunction(d, context.ReadOnlyClone(), expressionNode, subtract, false)
|
||||
}
|
||||
|
||||
func subtractArray(d *dataTreeNavigator, context Context, lhs *CandidateNode, rhs *CandidateNode) (*CandidateNode, error) {
|
||||
newLhsArray := make([]*yaml.Node, 0)
|
||||
|
||||
for lindex := 0; lindex < len(lhs.Node.Content); lindex = lindex + 1 {
|
||||
shouldInclude := true
|
||||
for rindex := 0; rindex < len(rhs.Node.Content) && shouldInclude; rindex = rindex + 1 {
|
||||
if recursiveNodeEqual(lhs.Node.Content[lindex], rhs.Node.Content[rindex]) {
|
||||
shouldInclude = false
|
||||
}
|
||||
}
|
||||
if shouldInclude {
|
||||
newLhsArray = append(newLhsArray, lhs.Node.Content[lindex])
|
||||
}
|
||||
}
|
||||
lhs.Node.Content = newLhsArray
|
||||
return lhs, nil
|
||||
}
|
||||
|
||||
func subtract(d *dataTreeNavigator, context Context, lhs *CandidateNode, rhs *CandidateNode) (*CandidateNode, error) {
|
||||
lhs.Node = unwrapDoc(lhs.Node)
|
||||
rhs.Node = unwrapDoc(rhs.Node)
|
||||
@ -40,14 +58,13 @@ func subtract(d *dataTreeNavigator, context Context, lhs *CandidateNode, rhs *Ca
|
||||
case yaml.MappingNode:
|
||||
return nil, fmt.Errorf("Maps not yet supported for subtraction")
|
||||
case yaml.SequenceNode:
|
||||
return nil, fmt.Errorf("Sequences not yet supported for subtraction")
|
||||
// target.Node.Kind = yaml.SequenceNode
|
||||
// target.Node.Style = lhsNode.Style
|
||||
// target.Node.Tag = "!!seq"
|
||||
// target.Node.Content = append(lhsNode.Content, toNodes(rhs)...)
|
||||
if rhs.Node.Kind != yaml.SequenceNode {
|
||||
return nil, fmt.Errorf("%v (%v) cannot be subtracted from %v", rhs.Node.Tag, rhs.Path, lhsNode.Tag)
|
||||
}
|
||||
return subtractArray(d, context, lhs, rhs)
|
||||
case yaml.ScalarNode:
|
||||
if rhs.Node.Kind != yaml.ScalarNode {
|
||||
return nil, fmt.Errorf("%v (%v) cannot be added to a %v", rhs.Node.Tag, rhs.Path, lhsNode.Tag)
|
||||
return nil, fmt.Errorf("%v (%v) cannot be subtracted from %v", rhs.Node.Tag, rhs.Path, lhsNode.Tag)
|
||||
}
|
||||
target.Node.Kind = yaml.ScalarNode
|
||||
target.Node.Style = lhsNode.Style
|
||||
|
@ -13,6 +13,51 @@ var subtractOperatorScenarios = []expressionScenario{
|
||||
"D0, P[], (doc)::{}\n",
|
||||
},
|
||||
},
|
||||
{
|
||||
description: "Array subtraction",
|
||||
expression: `[1,2] - [2,3]`,
|
||||
expected: []string{
|
||||
"D0, P[], (!!seq)::- 1\n",
|
||||
},
|
||||
},
|
||||
{
|
||||
skipDoc: true,
|
||||
expression: `[2,1,2,2] - [2,3]`,
|
||||
expected: []string{
|
||||
"D0, P[], (!!seq)::- 1\n",
|
||||
},
|
||||
},
|
||||
{
|
||||
description: "Array subtraction with nested array",
|
||||
expression: `[[1], 1, 2] - [[1], 3]`,
|
||||
expected: []string{
|
||||
"D0, P[], (!!seq)::- 1\n- 2\n",
|
||||
},
|
||||
},
|
||||
{
|
||||
skipDoc: true,
|
||||
expression: `[[1], 1, [[[2]]]] - [[1], [[[3]]]]`,
|
||||
expected: []string{
|
||||
"D0, P[], (!!seq)::- 1\n- - - - 2\n",
|
||||
},
|
||||
},
|
||||
{
|
||||
description: "Array subtraction with nested object",
|
||||
subdescription: `Note that order of the keys does not matter`,
|
||||
document: `[{a: b, c: d}, {a: b}]`,
|
||||
expression: `. - [{"c": "d", "a": "b"}]`,
|
||||
expected: []string{
|
||||
"D0, P[], (!!seq)::[{a: b}]\n",
|
||||
},
|
||||
},
|
||||
{
|
||||
skipDoc: true,
|
||||
document: `[{a: [1], c: d}, {a: [2], c: d}, {a: b}]`,
|
||||
expression: `. - [{"c": "d", "a": [1]}]`,
|
||||
expected: []string{
|
||||
"D0, P[], (!!seq)::[{a: [2], c: d}, {a: b}]\n",
|
||||
},
|
||||
},
|
||||
{
|
||||
description: "Number subtraction - float",
|
||||
subdescription: "If the lhs or rhs are floats then the expression will be calculated with floats.",
|
||||
|
Loading…
Reference in New Issue
Block a user