mirror of
				https://github.com/taigrr/yq
				synced 2025-01-18 04:53:17 -08: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 | ||||
| ### Update parent to be the child value | ||||
| Given a sample.yml file of: | ||||
| @ -17,6 +23,23 @@ a: | ||||
|   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 | ||||
| Given a sample.yml file of: | ||||
| ```yaml | ||||
| @ -36,6 +59,24 @@ c: potatoe | ||||
| ``` | ||||
| 
 | ||||
| ### 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: | ||||
| ```yaml | ||||
| a: | ||||
							
								
								
									
										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} | ||||
| 
 | ||||
| // 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 AssignStyle = &OperationType{Type: "ASSIGN_STYLE", NumArgs: 2, Precedence: 40, Handler: AssignStyleOperator} | ||||
| var AssignTag = &OperationType{Type: "ASSIGN_TAG", NumArgs: 2, Precedence: 40, Handler: AssignTagOperator} | ||||
|  | ||||
| @ -2,15 +2,28 @@ package yqlib | ||||
| 
 | ||||
| import "container/list" | ||||
| 
 | ||||
| type AssignOpPreferences struct { | ||||
| 	UpdateAssign bool | ||||
| } | ||||
| 
 | ||||
| func AssignUpdateOperator(d *dataTreeNavigator, matchingNodes *list.List, pathNode *PathTreeNode) (*list.List, error) { | ||||
| 	lhs, err := d.GetMatchingNodes(matchingNodes, pathNode.Lhs) | ||||
| 	if err != nil { | ||||
| 		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() { | ||||
| 		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 { | ||||
| 			return nil, err | ||||
| @ -13,6 +13,14 @@ var assignOperatorScenarios = []expressionScenario{ | ||||
| 			"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", | ||||
| 		document:    `{a: fieldA, b: fieldB, c: fieldC}`, | ||||
| @ -24,6 +32,15 @@ var assignOperatorScenarios = []expressionScenario{ | ||||
| 	{ | ||||
| 		description: "Update string value", | ||||
| 		document:    `{a: {b: apple}}`, | ||||
| 		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{ | ||||
| 			"D0, P[], (doc)::{a: {b: frog}}\n", | ||||
| @ -99,5 +116,5 @@ func TestAssignOperatorScenarios(t *testing.T) { | ||||
| 	for _, tt := range assignOperatorScenarios { | ||||
| 		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} | ||||
| 	if rhs.Node.Kind == yaml.ScalarNode || rhs.Node.Kind == yaml.AliasNode { | ||||
| 		assignmentOp.OperationType = Assign | ||||
| 		assignmentOp.Preferences = &AssignOpPreferences{false} | ||||
| 	} | ||||
| 	rhsOp := &Operation{OperationType: ValueOp, CandidateNode: rhs} | ||||
| 
 | ||||
|  | ||||
| @ -215,11 +215,11 @@ func initLexer() (*lex.Lexer, error) { | ||||
| 	lexer.Add([]byte(`collect`), opToken(Collect)) | ||||
| 
 | ||||
| 	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(`\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(true)) | ||||
| @ -303,7 +303,7 @@ func (p *pathTokeniser) Tokenise(path string) ([]*Token, error) { | ||||
| 
 | ||||
| 			if index != len(tokens)-1 && token.AssignOperation != nil && | ||||
| 				tokens[index+1].TokenType == OperationToken && | ||||
| 				tokens[index+1].Operation.OperationType == PlainAssign { | ||||
| 				tokens[index+1].Operation.OperationType == Assign { | ||||
| 				token.Operation = token.AssignOperation | ||||
| 				skipNextToken = true | ||||
| 			} | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user