mirror of
https://github.com/taigrr/yq
synced 2025-01-18 04:53:17 -08:00
Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5a55869745 | ||
|
|
15e18bb98b |
@@ -59,6 +59,10 @@ func evaluateAll(cmd *cobra.Command, args []string) error {
|
|||||||
defer func() { writeInPlaceHandler.FinishWriteInPlace(completedSuccessfully) }()
|
defer func() { writeInPlaceHandler.FinishWriteInPlace(completedSuccessfully) }()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if nullInput && len(args) > 1 {
|
||||||
|
return errors.New("Cannot pass files in when using null-input flag")
|
||||||
|
}
|
||||||
|
|
||||||
printer := yqlib.NewPrinter(out, outputToJSON, unwrapScalar, colorsEnabled, indent, !noDocSeparators)
|
printer := yqlib.NewPrinter(out, outputToJSON, unwrapScalar, colorsEnabled, indent, !noDocSeparators)
|
||||||
|
|
||||||
allAtOnceEvaluator := yqlib.NewAllAtOnceEvaluator()
|
allAtOnceEvaluator := yqlib.NewAllAtOnceEvaluator()
|
||||||
|
|||||||
@@ -83,6 +83,10 @@ func evaluateSequence(cmd *cobra.Command, args []string) error {
|
|||||||
|
|
||||||
streamEvaluator := yqlib.NewStreamEvaluator()
|
streamEvaluator := yqlib.NewStreamEvaluator()
|
||||||
|
|
||||||
|
if nullInput && len(args) > 1 {
|
||||||
|
return errors.New("Cannot pass files in when using null-input flag")
|
||||||
|
}
|
||||||
|
|
||||||
switch len(args) {
|
switch len(args) {
|
||||||
case 0:
|
case 0:
|
||||||
if pipingStdIn {
|
if pipingStdIn {
|
||||||
|
|||||||
@@ -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.2.1"
|
Version = "4.3.0"
|
||||||
|
|
||||||
// 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.2.1
|
FROM mikefarah/yq:4.3.0
|
||||||
|
|
||||||
COPY entrypoint.sh /entrypoint.sh
|
COPY entrypoint.sh /entrypoint.sh
|
||||||
|
|
||||||
|
|||||||
@@ -1,76 +0,0 @@
|
|||||||
|
|
||||||
## Read string environment variable
|
|
||||||
Running
|
|
||||||
```bash
|
|
||||||
myenv="cat meow" yq eval --null-input '.a = env(myenv)'
|
|
||||||
```
|
|
||||||
will output
|
|
||||||
```yaml
|
|
||||||
a: cat meow
|
|
||||||
```
|
|
||||||
|
|
||||||
## Read boolean environment variable
|
|
||||||
Running
|
|
||||||
```bash
|
|
||||||
myenv="true" yq eval --null-input '.a = env(myenv)'
|
|
||||||
```
|
|
||||||
will output
|
|
||||||
```yaml
|
|
||||||
a: true
|
|
||||||
```
|
|
||||||
|
|
||||||
## Read numeric environment variable
|
|
||||||
Running
|
|
||||||
```bash
|
|
||||||
myenv="12" yq eval --null-input '.a = env(myenv)'
|
|
||||||
```
|
|
||||||
will output
|
|
||||||
```yaml
|
|
||||||
a: 12
|
|
||||||
```
|
|
||||||
|
|
||||||
## Read yaml environment variable
|
|
||||||
Running
|
|
||||||
```bash
|
|
||||||
myenv="{b: fish}" yq eval --null-input '.a = env(myenv)'
|
|
||||||
```
|
|
||||||
will output
|
|
||||||
```yaml
|
|
||||||
a: {b: fish}
|
|
||||||
```
|
|
||||||
|
|
||||||
## Read boolean environment variable as a string
|
|
||||||
Running
|
|
||||||
```bash
|
|
||||||
myenv="true" yq eval --null-input '.a = strenv(myenv)'
|
|
||||||
```
|
|
||||||
will output
|
|
||||||
```yaml
|
|
||||||
a: "true"
|
|
||||||
```
|
|
||||||
|
|
||||||
## Read numeric environment variable as a string
|
|
||||||
Running
|
|
||||||
```bash
|
|
||||||
myenv="12" yq eval --null-input '.a = strenv(myenv)'
|
|
||||||
```
|
|
||||||
will output
|
|
||||||
```yaml
|
|
||||||
a: "12"
|
|
||||||
```
|
|
||||||
|
|
||||||
## Dynamic key lookup with environment variable
|
|
||||||
Given a sample.yml file of:
|
|
||||||
```yaml
|
|
||||||
cat: meow
|
|
||||||
dog: woof
|
|
||||||
```
|
|
||||||
then
|
|
||||||
```bash
|
|
||||||
myenv="cat" yq eval '.[env(myenv)]' sample.yml
|
|
||||||
```
|
|
||||||
will output
|
|
||||||
```yaml
|
|
||||||
meow
|
|
||||||
```
|
|
||||||
|
|
||||||
@@ -48,24 +48,6 @@ will output
|
|||||||
frog
|
frog
|
||||||
```
|
```
|
||||||
|
|
||||||
## Dynamic keys
|
|
||||||
Expressions within [] can be used to dynamically lookup / calculate keys
|
|
||||||
|
|
||||||
Given a sample.yml file of:
|
|
||||||
```yaml
|
|
||||||
b: apple
|
|
||||||
apple: crispy yum
|
|
||||||
banana: soft yum
|
|
||||||
```
|
|
||||||
then
|
|
||||||
```bash
|
|
||||||
yq eval '.[.b]' sample.yml
|
|
||||||
```
|
|
||||||
will output
|
|
||||||
```yaml
|
|
||||||
crispy yum
|
|
||||||
```
|
|
||||||
|
|
||||||
## Children don't exist
|
## Children don't exist
|
||||||
Nodes are added dynamically while traversing
|
Nodes are added dynamically while traversing
|
||||||
|
|
||||||
|
|||||||
@@ -70,7 +70,6 @@ var TraverseArray = &OperationType{Type: "TRAVERSE_ARRAY", NumArgs: 1, Precedenc
|
|||||||
var DocumentFilter = &OperationType{Type: "DOCUMENT_FILTER", NumArgs: 0, Precedence: 50, Handler: TraversePathOperator}
|
var DocumentFilter = &OperationType{Type: "DOCUMENT_FILTER", NumArgs: 0, Precedence: 50, Handler: TraversePathOperator}
|
||||||
var SelfReference = &OperationType{Type: "SELF", NumArgs: 0, Precedence: 50, Handler: SelfOperator}
|
var SelfReference = &OperationType{Type: "SELF", NumArgs: 0, Precedence: 50, Handler: SelfOperator}
|
||||||
var ValueOp = &OperationType{Type: "VALUE", NumArgs: 0, Precedence: 50, Handler: ValueOperator}
|
var ValueOp = &OperationType{Type: "VALUE", NumArgs: 0, Precedence: 50, Handler: ValueOperator}
|
||||||
var EnvOp = &OperationType{Type: "ENV", NumArgs: 0, Precedence: 50, Handler: EnvOperator}
|
|
||||||
var Not = &OperationType{Type: "NOT", NumArgs: 0, Precedence: 50, Handler: NotOperator}
|
var Not = &OperationType{Type: "NOT", NumArgs: 0, Precedence: 50, Handler: NotOperator}
|
||||||
var Empty = &OperationType{Type: "EMPTY", NumArgs: 50, Handler: EmptyOperator}
|
var Empty = &OperationType{Type: "EMPTY", NumArgs: 50, Handler: EmptyOperator}
|
||||||
|
|
||||||
|
|||||||
@@ -1,52 +0,0 @@
|
|||||||
package yqlib
|
|
||||||
|
|
||||||
import (
|
|
||||||
"container/list"
|
|
||||||
"os"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
yaml "gopkg.in/yaml.v3"
|
|
||||||
)
|
|
||||||
|
|
||||||
type EnvOpPreferences struct {
|
|
||||||
StringValue bool
|
|
||||||
}
|
|
||||||
|
|
||||||
func EnvOperator(d *dataTreeNavigator, matchMap *list.List, pathNode *PathTreeNode) (*list.List, error) {
|
|
||||||
envName := pathNode.Operation.CandidateNode.Node.Value
|
|
||||||
log.Debug("EnvOperator, env name:", envName)
|
|
||||||
|
|
||||||
rawValue := os.Getenv(envName)
|
|
||||||
|
|
||||||
preferences := pathNode.Operation.Preferences.(*EnvOpPreferences)
|
|
||||||
|
|
||||||
var node *yaml.Node
|
|
||||||
if preferences.StringValue {
|
|
||||||
node = &yaml.Node{
|
|
||||||
Kind: yaml.ScalarNode,
|
|
||||||
Tag: "!!str",
|
|
||||||
Value: rawValue,
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
var dataBucket yaml.Node
|
|
||||||
decoder := yaml.NewDecoder(strings.NewReader(rawValue))
|
|
||||||
errorReading := decoder.Decode(&dataBucket)
|
|
||||||
if errorReading != nil {
|
|
||||||
return nil, errorReading
|
|
||||||
}
|
|
||||||
//first node is a doc
|
|
||||||
node = UnwrapDoc(&dataBucket)
|
|
||||||
}
|
|
||||||
log.Debug("ENV tag", node.Tag)
|
|
||||||
log.Debug("ENV value", node.Value)
|
|
||||||
log.Debug("ENV Kind", node.Kind)
|
|
||||||
|
|
||||||
target := &CandidateNode{
|
|
||||||
Path: make([]interface{}, 0),
|
|
||||||
Document: 0,
|
|
||||||
Filename: "",
|
|
||||||
Node: node,
|
|
||||||
}
|
|
||||||
|
|
||||||
return nodeToMap(target), nil
|
|
||||||
}
|
|
||||||
@@ -1,72 +0,0 @@
|
|||||||
package yqlib
|
|
||||||
|
|
||||||
import (
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
var envOperatorScenarios = []expressionScenario{
|
|
||||||
{
|
|
||||||
description: "Read string environment variable",
|
|
||||||
environmentVariable: "cat meow",
|
|
||||||
expression: `.a = env(myenv)`,
|
|
||||||
expected: []string{
|
|
||||||
"D0, P[], ()::a: cat meow\n",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
description: "Read boolean environment variable",
|
|
||||||
environmentVariable: "true",
|
|
||||||
expression: `.a = env(myenv)`,
|
|
||||||
expected: []string{
|
|
||||||
"D0, P[], ()::a: true\n",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
description: "Read numeric environment variable",
|
|
||||||
environmentVariable: "12",
|
|
||||||
expression: `.a = env(myenv)`,
|
|
||||||
expected: []string{
|
|
||||||
"D0, P[], ()::a: 12\n",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
description: "Read yaml environment variable",
|
|
||||||
environmentVariable: "{b: fish}",
|
|
||||||
expression: `.a = env(myenv)`,
|
|
||||||
expected: []string{
|
|
||||||
"D0, P[], ()::a: {b: fish}\n",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
description: "Read boolean environment variable as a string",
|
|
||||||
environmentVariable: "true",
|
|
||||||
expression: `.a = strenv(myenv)`,
|
|
||||||
expected: []string{
|
|
||||||
"D0, P[], ()::a: \"true\"\n",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
description: "Read numeric environment variable as a string",
|
|
||||||
environmentVariable: "12",
|
|
||||||
expression: `.a = strenv(myenv)`,
|
|
||||||
expected: []string{
|
|
||||||
"D0, P[], ()::a: \"12\"\n",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
description: "Dynamic key lookup with environment variable",
|
|
||||||
environmentVariable: "cat",
|
|
||||||
document: `{cat: meow, dog: woof}`,
|
|
||||||
expression: `.[env(myenv)]`,
|
|
||||||
expected: []string{
|
|
||||||
"D0, P[cat], (!!str)::meow\n",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestEnvOperatorScenarios(t *testing.T) {
|
|
||||||
for _, tt := range envOperatorScenarios {
|
|
||||||
testScenario(t, &tt)
|
|
||||||
}
|
|
||||||
documentScenarios(t, "Env Variable Operators", envOperatorScenarios)
|
|
||||||
}
|
|
||||||
@@ -54,15 +54,6 @@ var traversePathOperatorScenarios = []expressionScenario{
|
|||||||
"D0, P[{}], (!!str)::frog\n",
|
"D0, P[{}], (!!str)::frog\n",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
|
||||||
description: "Dynamic keys",
|
|
||||||
subdescription: `Expressions within [] can be used to dynamically lookup / calculate keys`,
|
|
||||||
document: `{b: apple, apple: crispy yum, banana: soft yum}`,
|
|
||||||
expression: `.[.b]`,
|
|
||||||
expected: []string{
|
|
||||||
"D0, P[apple], (!!str)::crispy yum\n",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
description: "Children don't exist",
|
description: "Children don't exist",
|
||||||
subdescription: "Nodes are added dynamically while traversing",
|
subdescription: "Nodes are added dynamically while traversing",
|
||||||
|
|||||||
@@ -17,7 +17,6 @@ import (
|
|||||||
type expressionScenario struct {
|
type expressionScenario struct {
|
||||||
description string
|
description string
|
||||||
subdescription string
|
subdescription string
|
||||||
environmentVariable string
|
|
||||||
document string
|
document string
|
||||||
document2 string
|
document2 string
|
||||||
expression string
|
expression string
|
||||||
@@ -62,10 +61,6 @@ func testScenario(t *testing.T, s *expressionScenario) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if s.environmentVariable != "" {
|
|
||||||
os.Setenv("myenv", s.environmentVariable)
|
|
||||||
}
|
|
||||||
|
|
||||||
results, err = treeNavigator.GetMatchingNodes(inputs, node)
|
results, err = treeNavigator.GetMatchingNodes(inputs, node)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -167,14 +162,6 @@ func documentInput(w *bufio.Writer, s expressionScenario) (string, string) {
|
|||||||
formattedDoc := ""
|
formattedDoc := ""
|
||||||
formattedDoc2 := ""
|
formattedDoc2 := ""
|
||||||
command := "eval"
|
command := "eval"
|
||||||
|
|
||||||
envCommand := ""
|
|
||||||
|
|
||||||
if s.environmentVariable != "" {
|
|
||||||
envCommand = fmt.Sprintf("myenv=\"%v\" ", s.environmentVariable)
|
|
||||||
os.Setenv("myenv", s.environmentVariable)
|
|
||||||
}
|
|
||||||
|
|
||||||
if s.document != "" {
|
if s.document != "" {
|
||||||
if s.dontFormatInputForDoc {
|
if s.dontFormatInputForDoc {
|
||||||
formattedDoc = s.document + "\n"
|
formattedDoc = s.document + "\n"
|
||||||
@@ -201,15 +188,14 @@ func documentInput(w *bufio.Writer, s expressionScenario) (string, string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
writeOrPanic(w, "then\n")
|
writeOrPanic(w, "then\n")
|
||||||
|
|
||||||
if s.expression != "" {
|
if s.expression != "" {
|
||||||
writeOrPanic(w, fmt.Sprintf("```bash\n%vyq %v '%v' %v\n```\n", envCommand, command, s.expression, files))
|
writeOrPanic(w, fmt.Sprintf("```bash\nyq %v '%v' %v\n```\n", command, s.expression, files))
|
||||||
} else {
|
} else {
|
||||||
writeOrPanic(w, fmt.Sprintf("```bash\n%vyq %v %v\n```\n", envCommand, command, files))
|
writeOrPanic(w, fmt.Sprintf("```bash\nyq %v %v\n```\n", command, files))
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
writeOrPanic(w, "Running\n")
|
writeOrPanic(w, "Running\n")
|
||||||
writeOrPanic(w, fmt.Sprintf("```bash\n%vyq %v --null-input '%v'\n```\n", envCommand, command, s.expression))
|
writeOrPanic(w, fmt.Sprintf("```bash\nyq %v --null-input '%v'\n```\n", command, s.expression))
|
||||||
}
|
}
|
||||||
return formattedDoc, formattedDoc2
|
return formattedDoc, formattedDoc2
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -178,28 +178,6 @@ func stringValue(wrapped bool) lex.Action {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func envOp(strenv bool) lex.Action {
|
|
||||||
return func(s *lex.Scanner, m *machines.Match) (interface{}, error) {
|
|
||||||
value := string(m.Bytes)
|
|
||||||
preferences := &EnvOpPreferences{}
|
|
||||||
|
|
||||||
if strenv {
|
|
||||||
// strenv( )
|
|
||||||
value = value[7 : len(value)-1]
|
|
||||||
preferences.StringValue = true
|
|
||||||
} else {
|
|
||||||
//env( )
|
|
||||||
value = value[4 : len(value)-1]
|
|
||||||
}
|
|
||||||
|
|
||||||
envOperation := CreateValueOperation(value, value)
|
|
||||||
envOperation.OperationType = EnvOp
|
|
||||||
envOperation.Preferences = preferences
|
|
||||||
|
|
||||||
return &Token{TokenType: OperationToken, Operation: envOperation}, nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func nullValue() lex.Action {
|
func nullValue() lex.Action {
|
||||||
return func(s *lex.Scanner, m *machines.Match) (interface{}, error) {
|
return func(s *lex.Scanner, m *machines.Match) (interface{}, error) {
|
||||||
return &Token{TokenType: OperationToken, Operation: CreateValueOperation(nil, string(m.Bytes))}, nil
|
return &Token{TokenType: OperationToken, Operation: CreateValueOperation(nil, string(m.Bytes))}, nil
|
||||||
@@ -288,8 +266,6 @@ func initLexer() (*lex.Lexer, error) {
|
|||||||
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(`env\([^\)]+\)`), envOp(false))
|
|
||||||
|
|
||||||
lexer.Add([]byte(`\[`), literalToken(OpenCollect, false))
|
lexer.Add([]byte(`\[`), literalToken(OpenCollect, false))
|
||||||
lexer.Add([]byte(`\]`), literalToken(CloseCollect, true))
|
lexer.Add([]byte(`\]`), literalToken(CloseCollect, true))
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
name: yq
|
name: yq
|
||||||
version: '4.2.1'
|
version: '4.3.0'
|
||||||
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