mirror of
https://github.com/mikefarah/yq.git
synced 2024-12-19 20:19:04 +00:00
Print path is more accurate than keys (i think)
This commit is contained in:
parent
854f5f0fc9
commit
728cbe991a
@ -1,11 +1,55 @@
|
||||
|
||||
# New Features
|
||||
- Keeps comments and formatting (e.g. inline arrays)!
|
||||
- Handles anchors!
|
||||
- Keeps yaml comments and formatting (string blocks are saved, number formatting is preserved, so it won't drop off trailing 0s for values like 0.10, which is important when that's a version entry )
|
||||
|
||||
- Handles anchors! (doc link)
|
||||
- Can specify yaml tags (e.g. !!int), quoting values no longer sufficient, need to specify the tag value instead.
|
||||
- Can print out matching paths and values when splatting (doc link)
|
||||
- JSON output works for all commands! Yaml files with multiple documents are printed out as one JSON document per line.
|
||||
- Deep splat (**) to match arbitrary paths, (doc link)
|
||||
|
||||
# Update scripts file format has changed to be more powerful. Comments can be added, and delete commands have been introduced.
|
||||
|
||||
# Breaking changes
|
||||
|
||||
## Update scripts file format has changed to be more powerful.
|
||||
Comments can be added, and delete commands have been introduced.
|
||||
|
||||
## Reading and splatting, matching results are printed once per line.
|
||||
e.g:
|
||||
|
||||
```json
|
||||
parent:
|
||||
childA:
|
||||
no: matches here
|
||||
childB:
|
||||
there: matches
|
||||
hi: no match
|
||||
there2: also matches
|
||||
```
|
||||
|
||||
yq r sample.yaml 'parent.*.there*'
|
||||
|
||||
old
|
||||
```yaml
|
||||
- null
|
||||
- - matches
|
||||
- also matches
|
||||
```
|
||||
|
||||
new
|
||||
```yaml
|
||||
matches
|
||||
also matches
|
||||
```
|
||||
|
||||
and you can print the matching paths:
|
||||
|
||||
yq r --printMode pv sample.yaml 'parent.*.there*'
|
||||
|
||||
```yaml
|
||||
parent.childB.there: matches
|
||||
parent.childB.there2: also matches
|
||||
```
|
||||
|
||||
# Merge command
|
||||
- New flag 'autocreates' missing entries in target by default, new flag to turn that off.
|
||||
|
@ -96,7 +96,7 @@ func TestReadCmd(t *testing.T) {
|
||||
|
||||
func TestReadWithKeyAndValueCmd(t *testing.T) {
|
||||
cmd := getRootCommand()
|
||||
result := test.RunCmd(cmd, "read -p kv examples/sample.yaml b.c")
|
||||
result := test.RunCmd(cmd, "read -p pv examples/sample.yaml b.c")
|
||||
if result.Error != nil {
|
||||
t.Error(result.Error)
|
||||
}
|
||||
@ -105,7 +105,7 @@ func TestReadWithKeyAndValueCmd(t *testing.T) {
|
||||
|
||||
func TestReadArrayCmd(t *testing.T) {
|
||||
cmd := getRootCommand()
|
||||
result := test.RunCmd(cmd, "read -p kv examples/sample.yaml b.e.1.name")
|
||||
result := test.RunCmd(cmd, "read -p pv examples/sample.yaml b.e.1.name")
|
||||
if result.Error != nil {
|
||||
t.Error(result.Error)
|
||||
}
|
||||
@ -114,7 +114,7 @@ func TestReadArrayCmd(t *testing.T) {
|
||||
|
||||
func TestReadDeepSplatCmd(t *testing.T) {
|
||||
cmd := getRootCommand()
|
||||
result := test.RunCmd(cmd, "read -p kv examples/sample.yaml b.**")
|
||||
result := test.RunCmd(cmd, "read -p pv examples/sample.yaml b.**")
|
||||
if result.Error != nil {
|
||||
t.Error(result.Error)
|
||||
}
|
||||
@ -132,7 +132,7 @@ b.e.[1].value: 4
|
||||
|
||||
func TestReadDeepSplatWithSuffixCmd(t *testing.T) {
|
||||
cmd := getRootCommand()
|
||||
result := test.RunCmd(cmd, "read -p kv examples/sample.yaml b.**.name")
|
||||
result := test.RunCmd(cmd, "read -p pv examples/sample.yaml b.**.name")
|
||||
if result.Error != nil {
|
||||
t.Error(result.Error)
|
||||
}
|
||||
@ -144,7 +144,7 @@ b.e.[1].name: sam
|
||||
|
||||
func TestReadWithKeyCmd(t *testing.T) {
|
||||
cmd := getRootCommand()
|
||||
result := test.RunCmd(cmd, "read -p k examples/sample.yaml b.c")
|
||||
result := test.RunCmd(cmd, "read -p p examples/sample.yaml b.c")
|
||||
if result.Error != nil {
|
||||
t.Error(result.Error)
|
||||
}
|
||||
@ -162,7 +162,7 @@ func TestReadAnchorsCmd(t *testing.T) {
|
||||
|
||||
func TestReadAnchorsWithKeyAndValueCmd(t *testing.T) {
|
||||
cmd := getRootCommand()
|
||||
result := test.RunCmd(cmd, "read -p kv examples/simple-anchor.yaml foobar.a")
|
||||
result := test.RunCmd(cmd, "read -p pv examples/simple-anchor.yaml foobar.a")
|
||||
if result.Error != nil {
|
||||
t.Error(result.Error)
|
||||
}
|
||||
@ -189,7 +189,7 @@ func TestReadMergeAnchorsOverrideCmd(t *testing.T) {
|
||||
|
||||
func TestReadMergeAnchorsPrefixMatchCmd(t *testing.T) {
|
||||
cmd := getRootCommand()
|
||||
result := test.RunCmd(cmd, "r -p kv examples/merge-anchor.yaml foobar.th*")
|
||||
result := test.RunCmd(cmd, "r -p pv examples/merge-anchor.yaml foobar.th*")
|
||||
if result.Error != nil {
|
||||
t.Error(result.Error)
|
||||
}
|
||||
@ -271,7 +271,7 @@ func TestReadMultiCmd(t *testing.T) {
|
||||
|
||||
func TestReadMultiWithKeyAndValueCmd(t *testing.T) {
|
||||
cmd := getRootCommand()
|
||||
result := test.RunCmd(cmd, "read -p vk -d 1 examples/multiple_docs.yaml another.document")
|
||||
result := test.RunCmd(cmd, "read -p vp -d 1 examples/multiple_docs.yaml another.document")
|
||||
if result.Error != nil {
|
||||
t.Error(result.Error)
|
||||
}
|
||||
@ -292,7 +292,7 @@ third document`, result.Output)
|
||||
|
||||
func TestReadMultiAllWithKeyAndValueCmd(t *testing.T) {
|
||||
cmd := getRootCommand()
|
||||
result := test.RunCmd(cmd, "read -p kv -d* examples/multiple_docs.yaml commonKey")
|
||||
result := test.RunCmd(cmd, "read -p pv -d* examples/multiple_docs.yaml commonKey")
|
||||
if result.Error != nil {
|
||||
t.Error(result.Error)
|
||||
}
|
||||
@ -372,7 +372,7 @@ gather_facts: true
|
||||
|
||||
func TestReadCmd_ArrayYaml_SplatWithKeyAndValueCmd(t *testing.T) {
|
||||
cmd := getRootCommand()
|
||||
result := test.RunCmd(cmd, "read -p kv examples/array.yaml [*]")
|
||||
result := test.RunCmd(cmd, "read -p pv examples/array.yaml [*]")
|
||||
if result.Error != nil {
|
||||
t.Error(result.Error)
|
||||
}
|
||||
@ -394,7 +394,7 @@ func TestReadCmd_ArrayYaml_SplatWithKeyAndValueCmd(t *testing.T) {
|
||||
|
||||
func TestReadCmd_ArrayYaml_SplatWithKeyCmd(t *testing.T) {
|
||||
cmd := getRootCommand()
|
||||
result := test.RunCmd(cmd, "read -p k examples/array.yaml [*]")
|
||||
result := test.RunCmd(cmd, "read -p p examples/array.yaml [*]")
|
||||
if result.Error != nil {
|
||||
t.Error(result.Error)
|
||||
}
|
||||
@ -494,7 +494,7 @@ func TestReadCmd_Verbose(t *testing.T) {
|
||||
if result.Error != nil {
|
||||
t.Error(result.Error)
|
||||
}
|
||||
test.AssertResult(t, "2\n", result.Output)
|
||||
test.AssertResult(t, "2", result.Output)
|
||||
}
|
||||
|
||||
// func TestReadCmd_ToJson(t *testing.T) {
|
||||
@ -559,7 +559,7 @@ b:
|
||||
defer test.RemoveTempYamlFile(filename)
|
||||
|
||||
cmd := getRootCommand()
|
||||
result := test.RunCmd(cmd, fmt.Sprintf("read -p kv %s b.there*.c", filename))
|
||||
result := test.RunCmd(cmd, fmt.Sprintf("read -p pv %s b.there*.c", filename))
|
||||
if result.Error != nil {
|
||||
t.Error(result.Error)
|
||||
}
|
||||
@ -587,7 +587,7 @@ b:
|
||||
defer test.RemoveTempYamlFile(filename)
|
||||
|
||||
cmd := getRootCommand()
|
||||
result := test.RunCmd(cmd, fmt.Sprintf("read -p k %s b.there*.c", filename))
|
||||
result := test.RunCmd(cmd, fmt.Sprintf("read -p p %s b.there*.c", filename))
|
||||
if result.Error != nil {
|
||||
t.Error(result.Error)
|
||||
}
|
||||
@ -871,6 +871,28 @@ func TestWriteCmdScript(t *testing.T) {
|
||||
test.AssertResult(t, expectedOutput, result.Output)
|
||||
}
|
||||
|
||||
func TestWriteCmdEmptyScript(t *testing.T) {
|
||||
content := `b:
|
||||
c: 3
|
||||
`
|
||||
filename := test.WriteTempYamlFile(content)
|
||||
defer test.RemoveTempYamlFile(filename)
|
||||
|
||||
updateScript := ``
|
||||
scriptFilename := test.WriteTempYamlFile(updateScript)
|
||||
defer test.RemoveTempYamlFile(scriptFilename)
|
||||
|
||||
cmd := getRootCommand()
|
||||
result := test.RunCmd(cmd, fmt.Sprintf("write --script %s %s", scriptFilename, filename))
|
||||
if result.Error != nil {
|
||||
t.Error(result.Error)
|
||||
}
|
||||
expectedOutput := `b:
|
||||
c: 3
|
||||
`
|
||||
test.AssertResult(t, expectedOutput, result.Output)
|
||||
}
|
||||
|
||||
func TestWriteMultiCmd(t *testing.T) {
|
||||
content := `b:
|
||||
c: 3
|
||||
|
19
yq.go
19
yq.go
@ -107,7 +107,7 @@ yq r -- things.yaml --key-starting-with-dashes.blah
|
||||
RunE: readProperty,
|
||||
}
|
||||
cmdRead.PersistentFlags().StringVarP(&docIndex, "doc", "d", "0", "process document index number (0 based, * for all documents)")
|
||||
cmdRead.PersistentFlags().StringVarP(&printMode, "printMode", "p", "v", "print mode (v (values, default), k (keys), kv (key and value pairs)")
|
||||
cmdRead.PersistentFlags().StringVarP(&printMode, "printMode", "p", "v", "print mode (v (values, default), p (paths), pv (path and value pairs)")
|
||||
return cmdRead
|
||||
}
|
||||
|
||||
@ -218,7 +218,7 @@ Note that you can give a create script to perform more sophisticated yaml. This
|
||||
`,
|
||||
RunE: newProperty,
|
||||
}
|
||||
cmdNew.PersistentFlags().StringVarP(&writeScript, "script", "s", "", "yaml script for updating yaml")
|
||||
cmdNew.PersistentFlags().StringVarP(&writeScript, "script", "s", "", "yaml script for creating yaml")
|
||||
cmdNew.PersistentFlags().StringVarP(&customTag, "tag", "t", "", "set yaml tag (e.g. !!int)")
|
||||
return cmdNew
|
||||
}
|
||||
@ -323,6 +323,11 @@ func appendDocument(originalMatchingNodes []*yqlib.NodeContext, dataBucket yaml.
|
||||
}
|
||||
|
||||
func printValue(node *yaml.Node, cmd *cobra.Command) error {
|
||||
if node.Kind == yaml.ScalarNode {
|
||||
cmd.Print(node.Value)
|
||||
return nil
|
||||
}
|
||||
|
||||
bufferedWriter := bufio.NewWriter(cmd.OutOrStdout())
|
||||
defer safelyFlush(bufferedWriter)
|
||||
|
||||
@ -346,12 +351,12 @@ func printResults(matchingNodes []*yqlib.NodeContext, cmd *cobra.Command) error
|
||||
|
||||
for index, mappedDoc := range matchingNodes {
|
||||
switch printMode {
|
||||
case "k":
|
||||
case "p":
|
||||
cmd.Print(lib.PathStackToString(mappedDoc.PathStack))
|
||||
if index < len(matchingNodes)-1 {
|
||||
cmd.Print("\n")
|
||||
}
|
||||
case "kv", "vk":
|
||||
case "pv", "vp":
|
||||
// put it into a node and print that.
|
||||
var parentNode = yaml.Node{Kind: yaml.MappingNode}
|
||||
parentNode.Content = make([]*yaml.Node, 2)
|
||||
@ -601,9 +606,13 @@ func readUpdateCommands(args []string, expectedArgs int, badArgsMessage string)
|
||||
var updateCommands []yqlib.UpdateCommand = make([]yqlib.UpdateCommand, 0)
|
||||
if writeScript != "" {
|
||||
var parsedCommands = make([]updateCommandParsed, 0)
|
||||
if err := readData(writeScript, 0, &parsedCommands); err != nil {
|
||||
|
||||
err := readData(writeScript, 0, &parsedCommands)
|
||||
|
||||
if err != nil && err != io.EOF {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
log.Debugf("Read write commands file '%v'", parsedCommands)
|
||||
for index := range parsedCommands {
|
||||
parsedCommand := parsedCommands[index]
|
||||
|
Loading…
Reference in New Issue
Block a user