mirror of
https://github.com/taigrr/yq
synced 2025-01-18 04:53:17 -08:00
Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
afebf0e621 | ||
|
|
dc464a5b10 | ||
|
|
5340ed0ad3 |
@@ -11,7 +11,7 @@ var (
|
|||||||
GitDescribe string
|
GitDescribe string
|
||||||
|
|
||||||
// Version is main version number that is being run at the moment.
|
// Version is main version number that is being run at the moment.
|
||||||
Version = "4.9.0"
|
Version = "4.9.1"
|
||||||
|
|
||||||
// VersionPrerelease is a pre-release marker for the version. If this is "" (empty string)
|
// VersionPrerelease is a pre-release marker for the version. If this is "" (empty string)
|
||||||
// then it means that it is a final release. Otherwise, this is a pre-release
|
// then it means that it is a final release. Otherwise, this is a pre-release
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
FROM mikefarah/yq:4.9.0
|
FROM mikefarah/yq:4.9.1
|
||||||
|
|
||||||
COPY entrypoint.sh /entrypoint.sh
|
COPY entrypoint.sh /entrypoint.sh
|
||||||
|
|
||||||
|
|||||||
@@ -12,6 +12,11 @@ var pathTests = []struct {
|
|||||||
expectedTokens []interface{}
|
expectedTokens []interface{}
|
||||||
expectedPostFix []interface{}
|
expectedPostFix []interface{}
|
||||||
}{
|
}{
|
||||||
|
{
|
||||||
|
`"\""`,
|
||||||
|
append(make([]interface{}, 0), "\" (string)"),
|
||||||
|
append(make([]interface{}, 0), "\" (string)"),
|
||||||
|
},
|
||||||
{
|
{
|
||||||
`[]|join(".")`,
|
`[]|join(".")`,
|
||||||
append(make([]interface{}, 0), "[", "EMPTY", "]", "PIPE", "JOIN", "(", ". (string)", ")"),
|
append(make([]interface{}, 0), "[", "EMPTY", "]", "PIPE", "JOIN", "(", ". (string)", ")"),
|
||||||
|
|||||||
@@ -189,6 +189,7 @@ func stringValue(wrapped bool) lex.Action {
|
|||||||
if wrapped {
|
if wrapped {
|
||||||
value = unwrap(value)
|
value = unwrap(value)
|
||||||
}
|
}
|
||||||
|
value = strings.ReplaceAll(value, "\\\"", "\"")
|
||||||
return &token{TokenType: operationToken, Operation: createValueOperation(value, value)}, nil
|
return &token{TokenType: operationToken, Operation: createValueOperation(value, value)}, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -334,7 +335,7 @@ func initLexer() (*lex.Lexer, error) {
|
|||||||
lexer.Add([]byte(`[Nn][Uu][Ll][Ll]`), nullValue())
|
lexer.Add([]byte(`[Nn][Uu][Ll][Ll]`), nullValue())
|
||||||
lexer.Add([]byte(`~`), nullValue())
|
lexer.Add([]byte(`~`), nullValue())
|
||||||
|
|
||||||
lexer.Add([]byte(`"[^"]*"`), stringValue(true))
|
lexer.Add([]byte(`"([^"\\]*(\\.[^"\\]*)*)"`), stringValue(true))
|
||||||
lexer.Add([]byte(`strenv\([^\)]+\)`), envOp(true))
|
lexer.Add([]byte(`strenv\([^\)]+\)`), envOp(true))
|
||||||
lexer.Add([]byte(`env\([^\)]+\)`), envOp(false))
|
lexer.Add([]byte(`env\([^\)]+\)`), envOp(false))
|
||||||
|
|
||||||
|
|||||||
@@ -10,14 +10,26 @@ func equalsOperator(d *dataTreeNavigator, context Context, expressionNode *Expre
|
|||||||
func isEquals(flip bool) func(d *dataTreeNavigator, context Context, lhs *CandidateNode, rhs *CandidateNode) (*CandidateNode, error) {
|
func isEquals(flip bool) func(d *dataTreeNavigator, context Context, lhs *CandidateNode, rhs *CandidateNode) (*CandidateNode, error) {
|
||||||
return func(d *dataTreeNavigator, context Context, lhs *CandidateNode, rhs *CandidateNode) (*CandidateNode, error) {
|
return func(d *dataTreeNavigator, context Context, lhs *CandidateNode, rhs *CandidateNode) (*CandidateNode, error) {
|
||||||
value := false
|
value := false
|
||||||
|
log.Debugf("-- isEquals cross function")
|
||||||
if lhs == nil && rhs == nil {
|
if lhs == nil && rhs == nil {
|
||||||
owner := &CandidateNode{}
|
owner := &CandidateNode{}
|
||||||
return createBooleanCandidate(owner, !flip), nil
|
return createBooleanCandidate(owner, !flip), nil
|
||||||
} else if lhs == nil {
|
} else if lhs == nil {
|
||||||
return createBooleanCandidate(rhs, flip), nil
|
log.Debugf("lhs nil, but rhs is not")
|
||||||
|
rhsNode := unwrapDoc(rhs.Node)
|
||||||
|
value := rhsNode.Tag == "!!null"
|
||||||
|
if flip {
|
||||||
|
value = !value
|
||||||
|
}
|
||||||
|
return createBooleanCandidate(rhs, value), nil
|
||||||
} else if rhs == nil {
|
} else if rhs == nil {
|
||||||
return createBooleanCandidate(lhs, flip), nil
|
log.Debugf("lhs not nil, but rhs is")
|
||||||
|
lhsNode := unwrapDoc(lhs.Node)
|
||||||
|
value := lhsNode.Tag == "!!null"
|
||||||
|
if flip {
|
||||||
|
value = !value
|
||||||
|
}
|
||||||
|
return createBooleanCandidate(lhs, value), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
lhsNode := unwrapDoc(lhs.Node)
|
lhsNode := unwrapDoc(lhs.Node)
|
||||||
@@ -37,6 +49,6 @@ func isEquals(flip bool) func(d *dataTreeNavigator, context Context, lhs *Candid
|
|||||||
}
|
}
|
||||||
|
|
||||||
func notEqualsOperator(d *dataTreeNavigator, context Context, expressionNode *ExpressionNode) (Context, error) {
|
func notEqualsOperator(d *dataTreeNavigator, context Context, expressionNode *ExpressionNode) (Context, error) {
|
||||||
log.Debugf("-- equalsOperation")
|
log.Debugf("-- notEqualsOperator")
|
||||||
return crossFunction(d, context, expressionNode, isEquals(true), true)
|
return crossFunction(d, context, expressionNode, isEquals(true), true)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,6 +14,28 @@ var equalsOperatorScenarios = []expressionScenario{
|
|||||||
"D0, P[], (!!bool)::false\n",
|
"D0, P[], (!!bool)::false\n",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
skipDoc: true,
|
||||||
|
document: "{a: {b: 10}}",
|
||||||
|
expression: "select(.c != null)",
|
||||||
|
expected: []string{},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
skipDoc: true,
|
||||||
|
document: "{a: {b: 10}}",
|
||||||
|
expression: "select(.d == .c)",
|
||||||
|
expected: []string{
|
||||||
|
"D0, P[], (doc)::{a: {b: 10}}\n",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
skipDoc: true,
|
||||||
|
document: "{a: {b: 10}}",
|
||||||
|
expression: "select(null == .c)",
|
||||||
|
expected: []string{
|
||||||
|
"D0, P[], (doc)::{a: {b: 10}}\n",
|
||||||
|
},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
skipDoc: true,
|
skipDoc: true,
|
||||||
document: "{a: { b: {things: \"\"}, f: [1], g: [] }}",
|
document: "{a: { b: {things: \"\"}, f: [1], g: [] }}",
|
||||||
|
|||||||
@@ -24,7 +24,9 @@ func selectOperator(d *dataTreeNavigator, context Context, expressionNode *Expre
|
|||||||
|
|
||||||
if first != nil {
|
if first != nil {
|
||||||
result := first.Value.(*CandidateNode)
|
result := first.Value.(*CandidateNode)
|
||||||
|
log.Debugf("result %v", NodeToString(result))
|
||||||
includeResult, errDecoding := isTruthy(result)
|
includeResult, errDecoding := isTruthy(result)
|
||||||
|
log.Debugf("isTruthy %v", includeResult)
|
||||||
if errDecoding != nil {
|
if errDecoding != nil {
|
||||||
return Context{}, errDecoding
|
return Context{}, errDecoding
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,7 +24,17 @@ func emptyOperator(d *dataTreeNavigator, context Context, expressionNode *Expres
|
|||||||
|
|
||||||
type crossFunctionCalculation func(d *dataTreeNavigator, context Context, lhs *CandidateNode, rhs *CandidateNode) (*CandidateNode, error)
|
type crossFunctionCalculation func(d *dataTreeNavigator, context Context, lhs *CandidateNode, rhs *CandidateNode) (*CandidateNode, error)
|
||||||
|
|
||||||
func resultsForRhs(d *dataTreeNavigator, context Context, lhsCandidate *CandidateNode, rhs Context, calculation crossFunctionCalculation, results *list.List) error {
|
func resultsForRhs(d *dataTreeNavigator, context Context, lhsCandidate *CandidateNode, rhs Context, calculation crossFunctionCalculation, results *list.List, calcWhenEmpty bool) error {
|
||||||
|
|
||||||
|
if calcWhenEmpty && rhs.MatchingNodes.Len() == 0 {
|
||||||
|
resultCandidate, err := calculation(d, context, lhsCandidate, nil)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
results.PushBack(resultCandidate)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
for rightEl := rhs.MatchingNodes.Front(); rightEl != nil; rightEl = rightEl.Next() {
|
for rightEl := rhs.MatchingNodes.Front(); rightEl != nil; rightEl = rightEl.Next() {
|
||||||
log.Debugf("Applying calc")
|
log.Debugf("Applying calc")
|
||||||
rhsCandidate := rightEl.Value.(*CandidateNode)
|
rhsCandidate := rightEl.Value.(*CandidateNode)
|
||||||
@@ -52,14 +62,7 @@ func doCrossFunc(d *dataTreeNavigator, context Context, expressionNode *Expressi
|
|||||||
}
|
}
|
||||||
|
|
||||||
if calcWhenEmpty && lhs.MatchingNodes.Len() == 0 {
|
if calcWhenEmpty && lhs.MatchingNodes.Len() == 0 {
|
||||||
if rhs.MatchingNodes.Len() == 0 {
|
err := resultsForRhs(d, context, nil, rhs, calculation, results, calcWhenEmpty)
|
||||||
resultCandidate, err := calculation(d, context, nil, nil)
|
|
||||||
if err != nil {
|
|
||||||
return Context{}, err
|
|
||||||
}
|
|
||||||
results.PushBack(resultCandidate)
|
|
||||||
}
|
|
||||||
err := resultsForRhs(d, context, nil, rhs, calculation, results)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return Context{}, err
|
return Context{}, err
|
||||||
}
|
}
|
||||||
@@ -68,7 +71,7 @@ func doCrossFunc(d *dataTreeNavigator, context Context, expressionNode *Expressi
|
|||||||
for el := lhs.MatchingNodes.Front(); el != nil; el = el.Next() {
|
for el := lhs.MatchingNodes.Front(); el != nil; el = el.Next() {
|
||||||
lhsCandidate := el.Value.(*CandidateNode)
|
lhsCandidate := el.Value.(*CandidateNode)
|
||||||
|
|
||||||
err := resultsForRhs(d, context, lhsCandidate, rhs, calculation, results)
|
err := resultsForRhs(d, context, lhsCandidate, rhs, calculation, results, calcWhenEmpty)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return Context{}, err
|
return Context{}, err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
name: yq
|
name: yq
|
||||||
version: '4.9.0'
|
version: '4.9.1'
|
||||||
summary: A lightweight and portable command-line YAML processor
|
summary: A lightweight and portable command-line YAML processor
|
||||||
description: |
|
description: |
|
||||||
The aim of the project is to be the jq or sed of yaml files.
|
The aim of the project is to be the jq or sed of yaml files.
|
||||||
|
|||||||
Reference in New Issue
Block a user