mirror of
https://github.com/mikefarah/yq.git
synced 2024-12-19 20:19:04 +00:00
Added plain assignment
This commit is contained in:
parent
36084a60a9
commit
75044e480c
@ -1,4 +1,10 @@
|
|||||||
Updates the LHS using the expression on the RHS. Note that the RHS runs against the _original_ LHS value, so that you can evaluate a new value based on the old (e.g. increment).
|
This operator is used to update node values. It can be used in either the:
|
||||||
|
|
||||||
|
### plain form: `=`
|
||||||
|
Which will assign the LHS node values to the RHS node values. The RHS expression is run against the matching nodes in the pipeline.
|
||||||
|
|
||||||
|
### relative form: `|=`
|
||||||
|
This will do a similar thing to the plain form, however, the RHS expression is run against _the LHS nodes_. This is useful for updating values based on old values, e.g. increment.
|
||||||
## Examples
|
## Examples
|
||||||
### Update parent to be the child value
|
### Update parent to be the child value
|
||||||
Given a sample.yml file of:
|
Given a sample.yml file of:
|
||||||
@ -17,6 +23,23 @@ a:
|
|||||||
g: foof
|
g: foof
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Update to be the sibling value
|
||||||
|
Given a sample.yml file of:
|
||||||
|
```yaml
|
||||||
|
a:
|
||||||
|
b: child
|
||||||
|
b: sibling
|
||||||
|
```
|
||||||
|
then
|
||||||
|
```bash
|
||||||
|
yq eval '.a = .b' sample.yml
|
||||||
|
```
|
||||||
|
will output
|
||||||
|
```yaml
|
||||||
|
a: sibling
|
||||||
|
b: sibling
|
||||||
|
```
|
||||||
|
|
||||||
### Updated multiple paths
|
### Updated multiple paths
|
||||||
Given a sample.yml file of:
|
Given a sample.yml file of:
|
||||||
```yaml
|
```yaml
|
||||||
@ -36,6 +59,24 @@ c: potatoe
|
|||||||
```
|
```
|
||||||
|
|
||||||
### Update string value
|
### Update string value
|
||||||
|
Given a sample.yml file of:
|
||||||
|
```yaml
|
||||||
|
a:
|
||||||
|
b: apple
|
||||||
|
```
|
||||||
|
then
|
||||||
|
```bash
|
||||||
|
yq eval '.a.b = "frog"' sample.yml
|
||||||
|
```
|
||||||
|
will output
|
||||||
|
```yaml
|
||||||
|
a:
|
||||||
|
b: frog
|
||||||
|
```
|
||||||
|
|
||||||
|
### Update string value via |=
|
||||||
|
Note there is no difference between `=` and `|=` when the RHS is a scalar
|
||||||
|
|
||||||
Given a sample.yml file of:
|
Given a sample.yml file of:
|
||||||
```yaml
|
```yaml
|
||||||
a:
|
a:
|
@ -33,7 +33,7 @@ e: true
|
|||||||
```
|
```
|
||||||
then
|
then
|
||||||
```bash
|
```bash
|
||||||
yq eval '(.. | select(tag == "!!int")) tag = "!!str"' sample.yml
|
yq eval '(.. | select(tag == "!!int")) tag= "!!str"' sample.yml
|
||||||
```
|
```
|
||||||
will output
|
will output
|
||||||
```yaml
|
```yaml
|
||||||
|
7
pkg/yqlib/doc/headers/Assign Operator.md
Normal file
7
pkg/yqlib/doc/headers/Assign Operator.md
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
This operator is used to update node values. It can be used in either the:
|
||||||
|
|
||||||
|
### plain form: `=`
|
||||||
|
Which will assign the LHS node values to the RHS node values. The RHS expression is run against the matching nodes in the pipeline.
|
||||||
|
|
||||||
|
### relative form: `|=`
|
||||||
|
This will do a similar thing to the plain form, however, the RHS expression is run against _the LHS nodes_. This is useful for updating values based on old values, e.g. increment.
|
@ -1 +0,0 @@
|
|||||||
Updates the LHS using the expression on the RHS. Note that the RHS runs against the _original_ LHS value, so that you can evaluate a new value based on the old (e.g. increment).
|
|
@ -37,8 +37,6 @@ var Union = &OperationType{Type: "UNION", NumArgs: 2, Precedence: 10, Handler: U
|
|||||||
|
|
||||||
var Assign = &OperationType{Type: "ASSIGN", NumArgs: 2, Precedence: 40, Handler: AssignUpdateOperator}
|
var Assign = &OperationType{Type: "ASSIGN", NumArgs: 2, Precedence: 40, Handler: AssignUpdateOperator}
|
||||||
|
|
||||||
// TODO: implement this
|
|
||||||
var PlainAssign = &OperationType{Type: "ASSIGN", NumArgs: 2, Precedence: 40, Handler: AssignUpdateOperator}
|
|
||||||
var AssignAttributes = &OperationType{Type: "ASSIGN_ATTRIBUTES", NumArgs: 2, Precedence: 40, Handler: AssignAttributesOperator}
|
var AssignAttributes = &OperationType{Type: "ASSIGN_ATTRIBUTES", NumArgs: 2, Precedence: 40, Handler: AssignAttributesOperator}
|
||||||
var AssignStyle = &OperationType{Type: "ASSIGN_STYLE", NumArgs: 2, Precedence: 40, Handler: AssignStyleOperator}
|
var AssignStyle = &OperationType{Type: "ASSIGN_STYLE", NumArgs: 2, Precedence: 40, Handler: AssignStyleOperator}
|
||||||
var AssignTag = &OperationType{Type: "ASSIGN_TAG", NumArgs: 2, Precedence: 40, Handler: AssignTagOperator}
|
var AssignTag = &OperationType{Type: "ASSIGN_TAG", NumArgs: 2, Precedence: 40, Handler: AssignTagOperator}
|
||||||
|
@ -2,15 +2,28 @@ package yqlib
|
|||||||
|
|
||||||
import "container/list"
|
import "container/list"
|
||||||
|
|
||||||
|
type AssignOpPreferences struct {
|
||||||
|
UpdateAssign bool
|
||||||
|
}
|
||||||
|
|
||||||
func AssignUpdateOperator(d *dataTreeNavigator, matchingNodes *list.List, pathNode *PathTreeNode) (*list.List, error) {
|
func AssignUpdateOperator(d *dataTreeNavigator, matchingNodes *list.List, pathNode *PathTreeNode) (*list.List, error) {
|
||||||
lhs, err := d.GetMatchingNodes(matchingNodes, pathNode.Lhs)
|
lhs, err := d.GetMatchingNodes(matchingNodes, pathNode.Lhs)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
preferences := pathNode.Operation.Preferences.(*AssignOpPreferences)
|
||||||
|
|
||||||
|
var rhs *list.List
|
||||||
|
if !preferences.UpdateAssign {
|
||||||
|
rhs, err = d.GetMatchingNodes(matchingNodes, pathNode.Rhs)
|
||||||
|
}
|
||||||
|
|
||||||
for el := lhs.Front(); el != nil; el = el.Next() {
|
for el := lhs.Front(); el != nil; el = el.Next() {
|
||||||
candidate := el.Value.(*CandidateNode)
|
candidate := el.Value.(*CandidateNode)
|
||||||
|
|
||||||
rhs, err := d.GetMatchingNodes(nodeToMap(candidate), pathNode.Rhs)
|
if preferences.UpdateAssign {
|
||||||
|
rhs, err = d.GetMatchingNodes(nodeToMap(candidate), pathNode.Rhs)
|
||||||
|
}
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
@ -13,6 +13,14 @@ var assignOperatorScenarios = []expressionScenario{
|
|||||||
"D0, P[], (doc)::{a: {g: foof}}\n",
|
"D0, P[], (doc)::{a: {g: foof}}\n",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
description: "Update to be the sibling value",
|
||||||
|
document: `{a: {b: child}, b: sibling}`,
|
||||||
|
expression: `.a = .b`,
|
||||||
|
expected: []string{
|
||||||
|
"D0, P[], (doc)::{a: sibling, b: sibling}\n",
|
||||||
|
},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
description: "Updated multiple paths",
|
description: "Updated multiple paths",
|
||||||
document: `{a: fieldA, b: fieldB, c: fieldC}`,
|
document: `{a: fieldA, b: fieldB, c: fieldC}`,
|
||||||
@ -24,7 +32,16 @@ var assignOperatorScenarios = []expressionScenario{
|
|||||||
{
|
{
|
||||||
description: "Update string value",
|
description: "Update string value",
|
||||||
document: `{a: {b: apple}}`,
|
document: `{a: {b: apple}}`,
|
||||||
expression: `.a.b |= "frog"`,
|
expression: `.a.b = "frog"`,
|
||||||
|
expected: []string{
|
||||||
|
"D0, P[], (doc)::{a: {b: frog}}\n",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
description: "Update string value via |=",
|
||||||
|
subdescription: "Note there is no difference between `=` and `|=` when the RHS is a scalar",
|
||||||
|
document: `{a: {b: apple}}`,
|
||||||
|
expression: `.a.b |= "frog"`,
|
||||||
expected: []string{
|
expected: []string{
|
||||||
"D0, P[], (doc)::{a: {b: frog}}\n",
|
"D0, P[], (doc)::{a: {b: frog}}\n",
|
||||||
},
|
},
|
||||||
@ -99,5 +116,5 @@ func TestAssignOperatorScenarios(t *testing.T) {
|
|||||||
for _, tt := range assignOperatorScenarios {
|
for _, tt := range assignOperatorScenarios {
|
||||||
testScenario(t, &tt)
|
testScenario(t, &tt)
|
||||||
}
|
}
|
||||||
documentScenarios(t, "Update Assign Operator", assignOperatorScenarios)
|
documentScenarios(t, "Assign Operator", assignOperatorScenarios)
|
||||||
}
|
}
|
@ -112,6 +112,7 @@ func applyAssignment(d *dataTreeNavigator, pathIndexToStartFrom int, lhs *Candid
|
|||||||
assignmentOp := &Operation{OperationType: AssignAttributes}
|
assignmentOp := &Operation{OperationType: AssignAttributes}
|
||||||
if rhs.Node.Kind == yaml.ScalarNode || rhs.Node.Kind == yaml.AliasNode {
|
if rhs.Node.Kind == yaml.ScalarNode || rhs.Node.Kind == yaml.AliasNode {
|
||||||
assignmentOp.OperationType = Assign
|
assignmentOp.OperationType = Assign
|
||||||
|
assignmentOp.Preferences = &AssignOpPreferences{false}
|
||||||
}
|
}
|
||||||
rhsOp := &Operation{OperationType: ValueOp, CandidateNode: rhs}
|
rhsOp := &Operation{OperationType: ValueOp, CandidateNode: rhs}
|
||||||
|
|
||||||
|
@ -215,11 +215,11 @@ func initLexer() (*lex.Lexer, error) {
|
|||||||
lexer.Add([]byte(`collect`), opToken(Collect))
|
lexer.Add([]byte(`collect`), opToken(Collect))
|
||||||
|
|
||||||
lexer.Add([]byte(`\s*==\s*`), opToken(Equals))
|
lexer.Add([]byte(`\s*==\s*`), opToken(Equals))
|
||||||
lexer.Add([]byte(`\s*=\s*`), opToken(PlainAssign))
|
lexer.Add([]byte(`\s*=\s*`), opTokenWithPrefs(Assign, nil, &AssignOpPreferences{false}))
|
||||||
|
|
||||||
lexer.Add([]byte(`del`), opToken(DeleteChild))
|
lexer.Add([]byte(`del`), opToken(DeleteChild))
|
||||||
|
|
||||||
lexer.Add([]byte(`\s*\|=\s*`), opToken(Assign))
|
lexer.Add([]byte(`\s*\|=\s*`), opTokenWithPrefs(Assign, nil, &AssignOpPreferences{true}))
|
||||||
|
|
||||||
lexer.Add([]byte(`\[-?[0-9]+\]`), arrayIndextoken(false))
|
lexer.Add([]byte(`\[-?[0-9]+\]`), arrayIndextoken(false))
|
||||||
lexer.Add([]byte(`\.\[-?[0-9]+\]`), arrayIndextoken(true))
|
lexer.Add([]byte(`\.\[-?[0-9]+\]`), arrayIndextoken(true))
|
||||||
@ -303,7 +303,7 @@ func (p *pathTokeniser) Tokenise(path string) ([]*Token, error) {
|
|||||||
|
|
||||||
if index != len(tokens)-1 && token.AssignOperation != nil &&
|
if index != len(tokens)-1 && token.AssignOperation != nil &&
|
||||||
tokens[index+1].TokenType == OperationToken &&
|
tokens[index+1].TokenType == OperationToken &&
|
||||||
tokens[index+1].Operation.OperationType == PlainAssign {
|
tokens[index+1].Operation.OperationType == Assign {
|
||||||
token.Operation = token.AssignOperation
|
token.Operation = token.AssignOperation
|
||||||
skipNextToken = true
|
skipNextToken = true
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user