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
|
## Number subtraction - float
|
||||||
If the lhs or rhs are floats then the expression will be calculated with floats.
|
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
|
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...
|
// yaml numbers can be hex encoded...
|
||||||
func parseInt(numberString string) (string, int64, error) {
|
func parseInt(numberString string) (string, int64, error) {
|
||||||
if strings.HasPrefix(numberString, "0x") ||
|
if strings.HasPrefix(numberString, "0x") ||
|
||||||
|
@ -5,7 +5,7 @@ import (
|
|||||||
|
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
yaml "gopkg.in/yaml.v3"
|
"gopkg.in/yaml.v3"
|
||||||
)
|
)
|
||||||
|
|
||||||
func createSubtractOp(lhs *ExpressionNode, rhs *ExpressionNode) *ExpressionNode {
|
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)
|
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) {
|
func subtract(d *dataTreeNavigator, context Context, lhs *CandidateNode, rhs *CandidateNode) (*CandidateNode, error) {
|
||||||
lhs.Node = unwrapDoc(lhs.Node)
|
lhs.Node = unwrapDoc(lhs.Node)
|
||||||
rhs.Node = unwrapDoc(rhs.Node)
|
rhs.Node = unwrapDoc(rhs.Node)
|
||||||
@ -40,14 +58,13 @@ func subtract(d *dataTreeNavigator, context Context, lhs *CandidateNode, rhs *Ca
|
|||||||
case yaml.MappingNode:
|
case yaml.MappingNode:
|
||||||
return nil, fmt.Errorf("Maps not yet supported for subtraction")
|
return nil, fmt.Errorf("Maps not yet supported for subtraction")
|
||||||
case yaml.SequenceNode:
|
case yaml.SequenceNode:
|
||||||
return nil, fmt.Errorf("Sequences not yet supported for subtraction")
|
if rhs.Node.Kind != yaml.SequenceNode {
|
||||||
// target.Node.Kind = yaml.SequenceNode
|
return nil, fmt.Errorf("%v (%v) cannot be subtracted from %v", rhs.Node.Tag, rhs.Path, lhsNode.Tag)
|
||||||
// target.Node.Style = lhsNode.Style
|
}
|
||||||
// target.Node.Tag = "!!seq"
|
return subtractArray(d, context, lhs, rhs)
|
||||||
// target.Node.Content = append(lhsNode.Content, toNodes(rhs)...)
|
|
||||||
case yaml.ScalarNode:
|
case yaml.ScalarNode:
|
||||||
if rhs.Node.Kind != 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.Kind = yaml.ScalarNode
|
||||||
target.Node.Style = lhsNode.Style
|
target.Node.Style = lhsNode.Style
|
||||||
|
@ -13,6 +13,51 @@ var subtractOperatorScenarios = []expressionScenario{
|
|||||||
"D0, P[], (doc)::{}\n",
|
"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",
|
description: "Number subtraction - float",
|
||||||
subdescription: "If the lhs or rhs are floats then the expression will be calculated with floats.",
|
subdescription: "If the lhs or rhs are floats then the expression will be calculated with floats.",
|
||||||
|
Loading…
Reference in New Issue
Block a user