diff --git a/pkg/yqlib/doc/Boolean Operators.md b/pkg/yqlib/doc/Boolean Operators.md new file mode 100644 index 00000000..198ab8da --- /dev/null +++ b/pkg/yqlib/doc/Boolean Operators.md @@ -0,0 +1,157 @@ +The `or` and `and` operators take two parameters and return a boolean result. These are most commonly used with the `select` operator to filter particular nodes. +## Examples +### Update node to be the child value +Given a sample.yml file of: +```yaml +a: + b: + g: foof +``` +then +```bash +yq eval '.a |= .b' sample.yml +``` +will output +```yaml +a: + g: foof +``` + +### Update node 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 +a: fieldA +b: fieldB +c: fieldC +``` +then +```bash +yq eval '(.a, .c) |= "potatoe"' sample.yml +``` +will output +```yaml +a: potatoe +b: fieldB +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: + b: apple +``` +then +```bash +yq eval '.a.b |= "frog"' sample.yml +``` +will output +```yaml +a: + b: frog +``` + +### Update selected results +Given a sample.yml file of: +```yaml +a: + b: apple + c: cactus +``` +then +```bash +yq eval '.a[] | select(. == "apple") |= "frog"' sample.yml +``` +will output +```yaml +a: + b: frog + c: cactus +``` + +### Update array values +Given a sample.yml file of: +```yaml +- candy +- apple +- sandy +``` +then +```bash +yq eval '.[] | select(. == "*andy") |= "bogs"' sample.yml +``` +will output +```yaml +- bogs +- apple +- bogs +``` + +### Update empty object +Given a sample.yml file of: +```yaml +'': null +``` +then +```bash +yq eval '.a.b |= "bogs"' sample.yml +``` +will output +```yaml +'': null +a: + b: bogs +``` + +### Update empty object and array +Given a sample.yml file of: +```yaml +'': null +``` +then +```bash +yq eval '.a.b[0] |= "bogs"' sample.yml +``` +will output +```yaml +'': null +a: + b: + - bogs +``` + diff --git a/pkg/yqlib/doc/headers/Boolean Operators.md b/pkg/yqlib/doc/headers/Boolean Operators.md new file mode 100644 index 00000000..15be7b7f --- /dev/null +++ b/pkg/yqlib/doc/headers/Boolean Operators.md @@ -0,0 +1 @@ +The `or` and `and` operators take two parameters and return a boolean result. These are most commonly used with the `select` operator to filter particular nodes. \ No newline at end of file diff --git a/pkg/yqlib/operator_booleans_test.go b/pkg/yqlib/operator_booleans_test.go index 61437926..6c9b1dea 100644 --- a/pkg/yqlib/operator_booleans_test.go +++ b/pkg/yqlib/operator_booleans_test.go @@ -6,18 +6,37 @@ import ( var booleanOperatorScenarios = []expressionScenario{ { - document: `{}`, - expression: `true or false`, + description: "OR example", + expression: `true or false`, expected: []string{ "D0, P[], (!!bool)::true\n", }, - }, { - document: `{}`, + }, + { + description: "AND example", + expression: `true and false`, + expected: []string{ + "D0, P[], (!!bool)::false\n", + }, + }, + { + document: "[{a: bird, b: dog}, {a: frog, b: bird}, {a: cat, b: fly}]", + description: "Matching nodes with select, equals and or", + expression: `.[] | select(.a == "cat" or .b == "dog")`, + expected: []string{ + "D0, P[], (!!map)::{a: bird, b: dog}\n", + "D0, P[], (!!map)::{a: cat, b: fly}\n", + }, + }, + { + skipDoc: true, expression: `false or false`, expected: []string{ "D0, P[], (!!bool)::false\n", }, - }, { + }, + { + skipDoc: true, document: `{a: true, b: false}`, expression: `.[] or (false, true)`, expected: []string{ @@ -33,4 +52,5 @@ func TestBooleanOperatorScenarios(t *testing.T) { for _, tt := range booleanOperatorScenarios { testScenario(t, &tt) } + documentScenarios(t, "Boolean Operators", assignOperatorScenarios) } diff --git a/pkg/yqlib/path_tokeniser.go b/pkg/yqlib/path_tokeniser.go index d9c78ef5..115b6d5b 100644 --- a/pkg/yqlib/path_tokeniser.go +++ b/pkg/yqlib/path_tokeniser.go @@ -196,6 +196,7 @@ func initLexer() (*lex.Lexer, error) { lexer.Add([]byte(`select`), opToken(Select)) lexer.Add([]byte(`explode`), opToken(Explode)) lexer.Add([]byte(`or`), opToken(Or)) + lexer.Add([]byte(`and`), opToken(And)) lexer.Add([]byte(`not`), opToken(Not)) lexer.Add([]byte(`documentIndex`), opToken(GetDocumentIndex))