mirror of
https://github.com/taigrr/yq
synced 2025-01-18 04:53:17 -08:00
Compare commits
24 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d84254c30f | ||
|
|
18bb4eee96 | ||
|
|
86b9fe3ef9 | ||
|
|
2c15048ddb | ||
|
|
ce2ee42f71 | ||
|
|
c2c49dcb17 | ||
|
|
60de18391c | ||
|
|
c86f8b426b | ||
|
|
b3532e0a61 | ||
|
|
b3b60665e4 | ||
|
|
df08b055cf | ||
|
|
e822313e82 | ||
|
|
a9f25c9d76 | ||
|
|
0a8c268dcc | ||
|
|
a0e70279a8 | ||
|
|
25c9c22d8d | ||
|
|
d46d555b07 | ||
|
|
fb87f638f2 | ||
|
|
facc81d1f4 | ||
|
|
c1f9065c68 | ||
|
|
be84cc3082 | ||
|
|
a2571da1a1 | ||
|
|
6d6e476ac8 | ||
|
|
ae0c042ae6 |
@@ -2,9 +2,16 @@ FROM golang:1.9 as builder
|
|||||||
|
|
||||||
WORKDIR /go/src/mikefarah/yq
|
WORKDIR /go/src/mikefarah/yq
|
||||||
|
|
||||||
|
# cache devtools
|
||||||
|
COPY ./scripts/devtools.sh /go/src/mikefarah/yq/scripts/devtools.sh
|
||||||
|
RUN ./scripts/devtools.sh
|
||||||
|
|
||||||
|
# cache vendor
|
||||||
|
COPY ./vendor/vendor.json /go/src/mikefarah/yq/vendor/vendor.json
|
||||||
|
RUN govendor sync
|
||||||
|
|
||||||
COPY . /go/src/mikefarah/yq
|
COPY . /go/src/mikefarah/yq
|
||||||
|
|
||||||
RUN scripts/devtools.sh
|
|
||||||
RUN CGO_ENABLED=0 make local build
|
RUN CGO_ENABLED=0 make local build
|
||||||
|
|
||||||
# Choose alpine as a base image to make this useful for CI, as many
|
# Choose alpine as a base image to make this useful for CI, as many
|
||||||
|
|||||||
16
README.md
16
README.md
@@ -20,7 +20,7 @@ sudo apt install yq -y
|
|||||||
```
|
```
|
||||||
or, [Download latest binary](https://github.com/mikefarah/yq/releases/latest) or alternatively:
|
or, [Download latest binary](https://github.com/mikefarah/yq/releases/latest) or alternatively:
|
||||||
```
|
```
|
||||||
go get github.com/mikefarah/yq
|
go get gopkg.in/mikefarah/yq.v2
|
||||||
```
|
```
|
||||||
|
|
||||||
## Run with Docker
|
## Run with Docker
|
||||||
@@ -50,6 +50,7 @@ docker run -it -v ${PWD}:/workdir mikefarah/yq sh
|
|||||||
- Pipe data in by using '-'
|
- Pipe data in by using '-'
|
||||||
- Merge multiple yaml files where each additional file sets values for missing or null value keys.
|
- Merge multiple yaml files where each additional file sets values for missing or null value keys.
|
||||||
- Merge multiple yaml files with overwrite to support overriding previous values.
|
- Merge multiple yaml files with overwrite to support overriding previous values.
|
||||||
|
- Supports multiple documents in a single yaml file
|
||||||
|
|
||||||
## [Usage](http://mikefarah.github.io/yq/)
|
## [Usage](http://mikefarah.github.io/yq/)
|
||||||
|
|
||||||
@@ -61,16 +62,15 @@ Usage:
|
|||||||
yq [command]
|
yq [command]
|
||||||
|
|
||||||
Available Commands:
|
Available Commands:
|
||||||
delete yq d [--inplace/-i] sample.yaml a.b.c
|
delete yq d [--inplace/-i] [--doc/-d index] sample.yaml a.b.c
|
||||||
help Help about any command
|
help Help about any command
|
||||||
merge yq m [--inplace/-i] [--overwrite/-x] sample.yaml sample2.yaml
|
merge yq m [--inplace/-i] [--doc/-d index] [--overwrite/-x] sample.yaml sample2.yaml
|
||||||
new yq n [--script/-s script_file] a.b.c newValueForC
|
new yq n [--script/-s script_file] a.b.c newValue
|
||||||
read yq r sample.yaml a.b.c
|
read yq r [--doc/-d index] sample.yaml a.b.c
|
||||||
write yq w [--inplace/-i] [--script/-s script_file] sample.yaml a.b.c newValueForC
|
write yq w [--inplace/-i] [--script/-s script_file] [--doc/-d index] sample.yaml a.b.c newValue
|
||||||
|
|
||||||
Flags:
|
Flags:
|
||||||
-h, --help help for yq
|
-h, --help help for yq
|
||||||
-j, --tojson output as json
|
|
||||||
-t, --trim trim yaml output (default true)
|
-t, --trim trim yaml output (default true)
|
||||||
-v, --verbose verbose mode
|
-v, --verbose verbose mode
|
||||||
-V, --version Print version information and quit
|
-V, --version Print version information and quit
|
||||||
@@ -81,7 +81,7 @@ Use "yq [command] --help" for more information about a command.
|
|||||||
## Contribute
|
## Contribute
|
||||||
1. `make [local] vendor`
|
1. `make [local] vendor`
|
||||||
2. add unit tests
|
2. add unit tests
|
||||||
3. apply changes
|
3. apply changes (use govendor with a preference to [gopkg](https://gopkg.in/) for package dependencies)
|
||||||
4. `make [local] build`
|
4. `make [local] build`
|
||||||
5. If required, update the user documentation
|
5. If required, update the user documentation
|
||||||
- Update README.md and/or documentation under the mkdocs folder
|
- Update README.md and/or documentation under the mkdocs folder
|
||||||
|
|||||||
284
commands_test.go
284
commands_test.go
@@ -5,7 +5,7 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/spf13/cobra"
|
"gopkg.in/spf13/cobra.v0"
|
||||||
)
|
)
|
||||||
|
|
||||||
func getRootCommand() *cobra.Command {
|
func getRootCommand() *cobra.Command {
|
||||||
@@ -73,30 +73,6 @@ func TestRootCmd_TrimShort(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestRootCmd_ToJsonLong(t *testing.T) {
|
|
||||||
cmd := getRootCommand()
|
|
||||||
result := runCmd(cmd, "--tojson")
|
|
||||||
if result.Error != nil {
|
|
||||||
t.Error(result.Error)
|
|
||||||
}
|
|
||||||
|
|
||||||
if !outputToJSON {
|
|
||||||
t.Error("Expected outputToJSON to be true")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestRootCmd_ToJsonShort(t *testing.T) {
|
|
||||||
cmd := getRootCommand()
|
|
||||||
result := runCmd(cmd, "-j")
|
|
||||||
if result.Error != nil {
|
|
||||||
t.Error(result.Error)
|
|
||||||
}
|
|
||||||
|
|
||||||
if !outputToJSON {
|
|
||||||
t.Error("Expected outputToJSON to be true")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestRootCmd_VersionShort(t *testing.T) {
|
func TestRootCmd_VersionShort(t *testing.T) {
|
||||||
cmd := getRootCommand()
|
cmd := getRootCommand()
|
||||||
result := runCmd(cmd, "-V")
|
result := runCmd(cmd, "-V")
|
||||||
@@ -128,6 +104,39 @@ func TestReadCmd(t *testing.T) {
|
|||||||
assertResult(t, "2\n", result.Output)
|
assertResult(t, "2\n", result.Output)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestReadInvalidDocumentIndexCmd(t *testing.T) {
|
||||||
|
cmd := getRootCommand()
|
||||||
|
result := runCmd(cmd, "read -df examples/sample.yaml b.c")
|
||||||
|
if result.Error == nil {
|
||||||
|
t.Error("Expected command to fail due to invalid path")
|
||||||
|
}
|
||||||
|
expectedOutput := `Document index f is not a integer or *: strconv.ParseInt: parsing "f": invalid syntax`
|
||||||
|
assertResult(t, expectedOutput, result.Error.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestReadBadDocumentIndexCmd(t *testing.T) {
|
||||||
|
cmd := getRootCommand()
|
||||||
|
result := runCmd(cmd, "read -d1 examples/sample.yaml b.c")
|
||||||
|
if result.Error == nil {
|
||||||
|
t.Error("Expected command to fail due to invalid path")
|
||||||
|
}
|
||||||
|
expectedOutput := `Asked to process document index 1 but there are only 1 document(s)`
|
||||||
|
assertResult(t, expectedOutput, result.Error.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestReadOrderCmd(t *testing.T) {
|
||||||
|
cmd := getRootCommand()
|
||||||
|
result := runCmd(cmd, "read examples/order.yaml")
|
||||||
|
if result.Error != nil {
|
||||||
|
t.Error(result.Error)
|
||||||
|
}
|
||||||
|
assertResult(t,
|
||||||
|
`version: 3
|
||||||
|
application: MyApp
|
||||||
|
`,
|
||||||
|
result.Output)
|
||||||
|
}
|
||||||
|
|
||||||
func TestReadMultiCmd(t *testing.T) {
|
func TestReadMultiCmd(t *testing.T) {
|
||||||
cmd := getRootCommand()
|
cmd := getRootCommand()
|
||||||
result := runCmd(cmd, "read -d 1 examples/multiple_docs.yaml another.document")
|
result := runCmd(cmd, "read -d 1 examples/multiple_docs.yaml another.document")
|
||||||
@@ -137,6 +146,19 @@ func TestReadMultiCmd(t *testing.T) {
|
|||||||
assertResult(t, "here\n", result.Output)
|
assertResult(t, "here\n", result.Output)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestReadMultiAllCmd(t *testing.T) {
|
||||||
|
cmd := getRootCommand()
|
||||||
|
result := runCmd(cmd, "read -d* examples/multiple_docs.yaml commonKey")
|
||||||
|
if result.Error != nil {
|
||||||
|
t.Error(result.Error)
|
||||||
|
}
|
||||||
|
assertResult(t,
|
||||||
|
`- first document
|
||||||
|
- second document
|
||||||
|
- third document
|
||||||
|
`, result.Output)
|
||||||
|
}
|
||||||
|
|
||||||
func TestReadCmd_ArrayYaml(t *testing.T) {
|
func TestReadCmd_ArrayYaml(t *testing.T) {
|
||||||
cmd := getRootCommand()
|
cmd := getRootCommand()
|
||||||
result := runCmd(cmd, "read examples/array.yaml [0].gather_facts")
|
result := runCmd(cmd, "read examples/array.yaml [0].gather_facts")
|
||||||
@@ -216,7 +238,7 @@ func TestReadCmd_ArrayYaml_ErrorBadPath(t *testing.T) {
|
|||||||
if result.Error == nil {
|
if result.Error == nil {
|
||||||
t.Error("Expected command to fail due to invalid path")
|
t.Error("Expected command to fail due to invalid path")
|
||||||
}
|
}
|
||||||
expectedOutput := `Error accessing array: strconv.ParseInt: parsing "x": invalid syntax`
|
expectedOutput := `Error reading path in document index 0: Error accessing array: strconv.ParseInt: parsing "x": invalid syntax`
|
||||||
assertResult(t, expectedOutput, result.Error.Error())
|
assertResult(t, expectedOutput, result.Error.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -226,7 +248,7 @@ func TestReadCmd_ArrayYaml_Splat_ErrorBadPath(t *testing.T) {
|
|||||||
if result.Error == nil {
|
if result.Error == nil {
|
||||||
t.Error("Expected command to fail due to invalid path")
|
t.Error("Expected command to fail due to invalid path")
|
||||||
}
|
}
|
||||||
expectedOutput := `Error accessing array: strconv.ParseInt: parsing "x": invalid syntax`
|
expectedOutput := `Error reading path in document index 0: Error accessing array: strconv.ParseInt: parsing "x": invalid syntax`
|
||||||
assertResult(t, expectedOutput, result.Error.Error())
|
assertResult(t, expectedOutput, result.Error.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -278,7 +300,7 @@ func TestReadCmd_ErrorBadPath(t *testing.T) {
|
|||||||
if result.Error == nil {
|
if result.Error == nil {
|
||||||
t.Fatal("Expected command to fail due to invalid path")
|
t.Fatal("Expected command to fail due to invalid path")
|
||||||
}
|
}
|
||||||
expectedOutput := `Error accessing array: strconv.ParseInt: parsing "x": invalid syntax`
|
expectedOutput := `Error reading path in document index 0: Error accessing array: strconv.ParseInt: parsing "x": invalid syntax`
|
||||||
assertResult(t, expectedOutput, result.Error.Error())
|
assertResult(t, expectedOutput, result.Error.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -302,7 +324,16 @@ func TestReadCmd_NoTrim(t *testing.T) {
|
|||||||
|
|
||||||
func TestReadCmd_ToJson(t *testing.T) {
|
func TestReadCmd_ToJson(t *testing.T) {
|
||||||
cmd := getRootCommand()
|
cmd := getRootCommand()
|
||||||
result := runCmd(cmd, "-j read examples/sample.yaml b.c")
|
result := runCmd(cmd, "read -j examples/sample.yaml b.c")
|
||||||
|
if result.Error != nil {
|
||||||
|
t.Error(result.Error)
|
||||||
|
}
|
||||||
|
assertResult(t, "2\n", result.Output)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestReadCmd_ToJsonLong(t *testing.T) {
|
||||||
|
cmd := getRootCommand()
|
||||||
|
result := runCmd(cmd, "read --tojson examples/sample.yaml b.c")
|
||||||
if result.Error != nil {
|
if result.Error != nil {
|
||||||
t.Error(result.Error)
|
t.Error(result.Error)
|
||||||
}
|
}
|
||||||
@@ -343,17 +374,6 @@ func TestNewCmd_Verbose(t *testing.T) {
|
|||||||
assertResult(t, expectedOutput, result.Output)
|
assertResult(t, expectedOutput, result.Output)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestNewCmd_ToJson(t *testing.T) {
|
|
||||||
cmd := getRootCommand()
|
|
||||||
result := runCmd(cmd, "-j new b.c 3")
|
|
||||||
if result.Error != nil {
|
|
||||||
t.Error(result.Error)
|
|
||||||
}
|
|
||||||
expectedOutput := `{"b":{"c":3}}
|
|
||||||
`
|
|
||||||
assertResult(t, expectedOutput, result.Output)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestWriteCmd(t *testing.T) {
|
func TestWriteCmd(t *testing.T) {
|
||||||
content := `b:
|
content := `b:
|
||||||
c: 3
|
c: 3
|
||||||
@@ -393,6 +413,58 @@ apples: ok
|
|||||||
`
|
`
|
||||||
assertResult(t, expectedOutput, result.Output)
|
assertResult(t, expectedOutput, result.Output)
|
||||||
}
|
}
|
||||||
|
func TestWriteInvalidDocumentIndexCmd(t *testing.T) {
|
||||||
|
content := `b:
|
||||||
|
c: 3
|
||||||
|
`
|
||||||
|
filename := writeTempYamlFile(content)
|
||||||
|
defer removeTempYamlFile(filename)
|
||||||
|
|
||||||
|
cmd := getRootCommand()
|
||||||
|
result := runCmd(cmd, fmt.Sprintf("write %s -df apples ok", filename))
|
||||||
|
if result.Error == nil {
|
||||||
|
t.Error("Expected command to fail due to invalid path")
|
||||||
|
}
|
||||||
|
expectedOutput := `Document index f is not a integer or *: strconv.ParseInt: parsing "f": invalid syntax`
|
||||||
|
assertResult(t, expectedOutput, result.Error.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestWriteBadDocumentIndexCmd(t *testing.T) {
|
||||||
|
content := `b:
|
||||||
|
c: 3
|
||||||
|
`
|
||||||
|
filename := writeTempYamlFile(content)
|
||||||
|
defer removeTempYamlFile(filename)
|
||||||
|
|
||||||
|
cmd := getRootCommand()
|
||||||
|
result := runCmd(cmd, fmt.Sprintf("write %s -d 1 apples ok", filename))
|
||||||
|
if result.Error == nil {
|
||||||
|
t.Error("Expected command to fail due to invalid path")
|
||||||
|
}
|
||||||
|
expectedOutput := `Asked to process document index 1 but there are only 1 document(s)`
|
||||||
|
assertResult(t, expectedOutput, result.Error.Error())
|
||||||
|
}
|
||||||
|
func TestWriteMultiAllCmd(t *testing.T) {
|
||||||
|
content := `b:
|
||||||
|
c: 3
|
||||||
|
---
|
||||||
|
apples: great
|
||||||
|
`
|
||||||
|
filename := writeTempYamlFile(content)
|
||||||
|
defer removeTempYamlFile(filename)
|
||||||
|
|
||||||
|
cmd := getRootCommand()
|
||||||
|
result := runCmd(cmd, fmt.Sprintf("write %s -d * apples ok", filename))
|
||||||
|
if result.Error != nil {
|
||||||
|
t.Error(result.Error)
|
||||||
|
}
|
||||||
|
expectedOutput := `b:
|
||||||
|
c: 3
|
||||||
|
apples: ok
|
||||||
|
---
|
||||||
|
apples: ok`
|
||||||
|
assertResult(t, expectedOutput, strings.Trim(result.Output, "\n "))
|
||||||
|
}
|
||||||
|
|
||||||
func TestWriteCmd_EmptyArray(t *testing.T) {
|
func TestWriteCmd_EmptyArray(t *testing.T) {
|
||||||
content := `b: 3`
|
content := `b: 3`
|
||||||
@@ -569,6 +641,29 @@ func TestDeleteYamlMulti(t *testing.T) {
|
|||||||
assertResult(t, expectedOutput, result.Output)
|
assertResult(t, expectedOutput, result.Output)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestDeleteYamlMultiAllCmd(t *testing.T) {
|
||||||
|
content := `b:
|
||||||
|
c: 3
|
||||||
|
apples: great
|
||||||
|
---
|
||||||
|
apples: great
|
||||||
|
something: else
|
||||||
|
`
|
||||||
|
filename := writeTempYamlFile(content)
|
||||||
|
defer removeTempYamlFile(filename)
|
||||||
|
|
||||||
|
cmd := getRootCommand()
|
||||||
|
result := runCmd(cmd, fmt.Sprintf("delete %s -d * apples", filename))
|
||||||
|
if result.Error != nil {
|
||||||
|
t.Error(result.Error)
|
||||||
|
}
|
||||||
|
expectedOutput := `b:
|
||||||
|
c: 3
|
||||||
|
---
|
||||||
|
something: else`
|
||||||
|
assertResult(t, expectedOutput, strings.Trim(result.Output, "\n "))
|
||||||
|
}
|
||||||
|
|
||||||
func TestMergeCmd(t *testing.T) {
|
func TestMergeCmd(t *testing.T) {
|
||||||
cmd := getRootCommand()
|
cmd := getRootCommand()
|
||||||
result := runCmd(cmd, "merge examples/data1.yaml examples/data2.yaml")
|
result := runCmd(cmd, "merge examples/data1.yaml examples/data2.yaml")
|
||||||
@@ -585,6 +680,54 @@ c:
|
|||||||
assertResult(t, expectedOutput, result.Output)
|
assertResult(t, expectedOutput, result.Output)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestMergeOverwriteCmd(t *testing.T) {
|
||||||
|
cmd := getRootCommand()
|
||||||
|
result := runCmd(cmd, "merge --overwrite examples/data1.yaml examples/data2.yaml")
|
||||||
|
if result.Error != nil {
|
||||||
|
t.Error(result.Error)
|
||||||
|
}
|
||||||
|
expectedOutput := `a: other
|
||||||
|
b:
|
||||||
|
- 3
|
||||||
|
- 4
|
||||||
|
c:
|
||||||
|
test: 1
|
||||||
|
`
|
||||||
|
assertResult(t, expectedOutput, result.Output)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMergeAppendCmd(t *testing.T) {
|
||||||
|
cmd := getRootCommand()
|
||||||
|
result := runCmd(cmd, "merge --append examples/data1.yaml examples/data2.yaml")
|
||||||
|
if result.Error != nil {
|
||||||
|
t.Error(result.Error)
|
||||||
|
}
|
||||||
|
expectedOutput := `a: simple
|
||||||
|
b:
|
||||||
|
- 1
|
||||||
|
- 2
|
||||||
|
- 3
|
||||||
|
- 4
|
||||||
|
c:
|
||||||
|
test: 1
|
||||||
|
`
|
||||||
|
assertResult(t, expectedOutput, result.Output)
|
||||||
|
}
|
||||||
|
func TestMergeArraysCmd(t *testing.T) {
|
||||||
|
cmd := getRootCommand()
|
||||||
|
result := runCmd(cmd, "merge --append examples/sample_array.yaml examples/sample_array_2.yaml")
|
||||||
|
if result.Error != nil {
|
||||||
|
t.Error(result.Error)
|
||||||
|
}
|
||||||
|
expectedOutput := `- 1
|
||||||
|
- 2
|
||||||
|
- 3
|
||||||
|
- 4
|
||||||
|
- 5
|
||||||
|
`
|
||||||
|
assertResult(t, expectedOutput, result.Output)
|
||||||
|
}
|
||||||
|
|
||||||
func TestMergeCmd_Multi(t *testing.T) {
|
func TestMergeCmd_Multi(t *testing.T) {
|
||||||
cmd := getRootCommand()
|
cmd := getRootCommand()
|
||||||
result := runCmd(cmd, "merge -d1 examples/multiple_docs_small.yaml examples/data2.yaml")
|
result := runCmd(cmd, "merge -d1 examples/multiple_docs_small.yaml examples/data2.yaml")
|
||||||
@@ -596,6 +739,9 @@ func TestMergeCmd_Multi(t *testing.T) {
|
|||||||
a: other
|
a: other
|
||||||
another:
|
another:
|
||||||
document: here
|
document: here
|
||||||
|
b:
|
||||||
|
- 3
|
||||||
|
- 4
|
||||||
c:
|
c:
|
||||||
test: 1
|
test: 1
|
||||||
---
|
---
|
||||||
@@ -604,6 +750,64 @@ c:
|
|||||||
assertResult(t, expectedOutput, strings.Trim(result.Output, "\n "))
|
assertResult(t, expectedOutput, strings.Trim(result.Output, "\n "))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestMergeYamlMultiAllCmd(t *testing.T) {
|
||||||
|
content := `b:
|
||||||
|
c: 3
|
||||||
|
apples: green
|
||||||
|
---
|
||||||
|
something: else`
|
||||||
|
filename := writeTempYamlFile(content)
|
||||||
|
defer removeTempYamlFile(filename)
|
||||||
|
|
||||||
|
mergeContent := `apples: red
|
||||||
|
something: good`
|
||||||
|
mergeFilename := writeTempYamlFile(mergeContent)
|
||||||
|
defer removeTempYamlFile(mergeFilename)
|
||||||
|
|
||||||
|
cmd := getRootCommand()
|
||||||
|
result := runCmd(cmd, fmt.Sprintf("merge -d* %s %s", filename, mergeFilename))
|
||||||
|
if result.Error != nil {
|
||||||
|
t.Error(result.Error)
|
||||||
|
}
|
||||||
|
expectedOutput := `apples: green
|
||||||
|
b:
|
||||||
|
c: 3
|
||||||
|
something: good
|
||||||
|
---
|
||||||
|
apples: red
|
||||||
|
something: else`
|
||||||
|
assertResult(t, expectedOutput, strings.Trim(result.Output, "\n "))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMergeYamlMultiAllOverwriteCmd(t *testing.T) {
|
||||||
|
content := `b:
|
||||||
|
c: 3
|
||||||
|
apples: green
|
||||||
|
---
|
||||||
|
something: else`
|
||||||
|
filename := writeTempYamlFile(content)
|
||||||
|
defer removeTempYamlFile(filename)
|
||||||
|
|
||||||
|
mergeContent := `apples: red
|
||||||
|
something: good`
|
||||||
|
mergeFilename := writeTempYamlFile(mergeContent)
|
||||||
|
defer removeTempYamlFile(mergeFilename)
|
||||||
|
|
||||||
|
cmd := getRootCommand()
|
||||||
|
result := runCmd(cmd, fmt.Sprintf("merge --overwrite -d* %s %s", filename, mergeFilename))
|
||||||
|
if result.Error != nil {
|
||||||
|
t.Error(result.Error)
|
||||||
|
}
|
||||||
|
expectedOutput := `apples: red
|
||||||
|
b:
|
||||||
|
c: 3
|
||||||
|
something: good
|
||||||
|
---
|
||||||
|
apples: red
|
||||||
|
something: good`
|
||||||
|
assertResult(t, expectedOutput, strings.Trim(result.Output, "\n "))
|
||||||
|
}
|
||||||
|
|
||||||
func TestMergeCmd_Error(t *testing.T) {
|
func TestMergeCmd_Error(t *testing.T) {
|
||||||
cmd := getRootCommand()
|
cmd := getRootCommand()
|
||||||
result := runCmd(cmd, "merge examples/data1.yaml")
|
result := runCmd(cmd, "merge examples/data1.yaml")
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
"gopkg.in/yaml.v2"
|
yaml "gopkg.in/mikefarah/yaml.v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
func entryInSlice(context yaml.MapSlice, key interface{}) *yaml.MapItem {
|
func entryInSlice(context yaml.MapSlice, key interface{}) *yaml.MapItem {
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import (
|
|||||||
"sort"
|
"sort"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
yaml "gopkg.in/yaml.v2"
|
yaml "gopkg.in/mikefarah/yaml.v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestReadMap_simple(t *testing.T) {
|
func TestReadMap_simple(t *testing.T) {
|
||||||
|
|||||||
6
debian/changelog
vendored
6
debian/changelog
vendored
@@ -1,3 +1,9 @@
|
|||||||
|
yq (2.0-0) bionic; urgency=medium
|
||||||
|
|
||||||
|
* Release 2.0.0
|
||||||
|
|
||||||
|
-- Roberto Mier EscandĂłn <rmescandon@gmail.com> Wed, 20 Jun 2018 10:29:53 +0200
|
||||||
|
|
||||||
yq (1.15-0) bionic; urgency=medium
|
yq (1.15-0) bionic; urgency=medium
|
||||||
|
|
||||||
* Release 1.15
|
* Release 1.15
|
||||||
|
|||||||
@@ -372,7 +372,7 @@
|
|||||||
<h1>Convert</h1>
|
<h1>Convert</h1>
|
||||||
|
|
||||||
<h3 id="yaml-to-json">Yaml to Json<a class="headerlink" href="#yaml-to-json" title="Permanent link">¶</a></h3>
|
<h3 id="yaml-to-json">Yaml to Json<a class="headerlink" href="#yaml-to-json" title="Permanent link">¶</a></h3>
|
||||||
<p>To convert output to json, use the --tojson (or -j) flag. This can be used with any command.</p>
|
<p>To convert output to json, use the --tojson (or -j) flag. This can only be used with the read command.</p>
|
||||||
<p>Given a sample.yaml file of:</p>
|
<p>Given a sample.yaml file of:</p>
|
||||||
<pre><code class="yaml">b:
|
<pre><code class="yaml">b:
|
||||||
c: 2
|
c: 2
|
||||||
|
|||||||
@@ -385,7 +385,7 @@
|
|||||||
|
|
||||||
<h1>Create</h1>
|
<h1>Create</h1>
|
||||||
|
|
||||||
<p>Yaml files can be created using the 'new' command. This works in the same way as the write command, but you don't pass in an existing Yaml file.</p>
|
<p>Yaml files can be created using the 'new' command. This works in the same way as the write command, but you don't pass in an existing Yaml file. Currently this does not support creating multiple documents in a single yaml file.</p>
|
||||||
<pre><code>yq n <path> <new value>
|
<pre><code>yq n <path> <new value>
|
||||||
</code></pre>
|
</code></pre>
|
||||||
|
|
||||||
|
|||||||
@@ -287,6 +287,20 @@
|
|||||||
Deleting nodes in-place
|
Deleting nodes in-place
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li class="md-nav__item">
|
||||||
|
<a href="#multiple-documents-delete-from-single-document" title="Multiple Documents - delete from single document" class="md-nav__link">
|
||||||
|
Multiple Documents - delete from single document
|
||||||
|
</a>
|
||||||
|
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li class="md-nav__item">
|
||||||
|
<a href="#multiple-documents-delete-from-all-documents" title="Multiple Documents - delete from all documents" class="md-nav__link">
|
||||||
|
Multiple Documents - delete from all documents
|
||||||
|
</a>
|
||||||
|
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
<li class="md-nav__item">
|
<li class="md-nav__item">
|
||||||
@@ -385,6 +399,20 @@
|
|||||||
Deleting nodes in-place
|
Deleting nodes in-place
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li class="md-nav__item">
|
||||||
|
<a href="#multiple-documents-delete-from-single-document" title="Multiple Documents - delete from single document" class="md-nav__link">
|
||||||
|
Multiple Documents - delete from single document
|
||||||
|
</a>
|
||||||
|
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li class="md-nav__item">
|
||||||
|
<a href="#multiple-documents-delete-from-all-documents" title="Multiple Documents - delete from all documents" class="md-nav__link">
|
||||||
|
Multiple Documents - delete from all documents
|
||||||
|
</a>
|
||||||
|
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
<li class="md-nav__item">
|
<li class="md-nav__item">
|
||||||
@@ -413,10 +441,9 @@
|
|||||||
|
|
||||||
<h1>Delete</h1>
|
<h1>Delete</h1>
|
||||||
|
|
||||||
<pre><code>yq d <yaml_file|json_file> <path_to_delete>
|
<pre><code>yq d <yaml_file> <path_to_delete>
|
||||||
</code></pre>
|
</code></pre>
|
||||||
|
|
||||||
<p>This command can take a json file as input too, and will output yaml unless specified to export as json (-j)</p>
|
|
||||||
<h3 id="to-stdout">To Stdout<a class="headerlink" href="#to-stdout" title="Permanent link">¶</a></h3>
|
<h3 id="to-stdout">To Stdout<a class="headerlink" href="#to-stdout" title="Permanent link">¶</a></h3>
|
||||||
<p>Given a sample.yaml file of:</p>
|
<p>Given a sample.yaml file of:</p>
|
||||||
<pre><code class="yaml">b:
|
<pre><code class="yaml">b:
|
||||||
@@ -469,6 +496,50 @@
|
|||||||
</code></pre>
|
</code></pre>
|
||||||
|
|
||||||
<p>will update the sample.yaml file so that the 'c' node is deleted</p>
|
<p>will update the sample.yaml file so that the 'c' node is deleted</p>
|
||||||
|
<h3 id="multiple-documents-delete-from-single-document">Multiple Documents - delete from single document<a class="headerlink" href="#multiple-documents-delete-from-single-document" title="Permanent link">¶</a></h3>
|
||||||
|
<p>Given a sample.yaml file of:</p>
|
||||||
|
<pre><code class="yaml">something: else
|
||||||
|
field: leaveMe
|
||||||
|
---
|
||||||
|
b:
|
||||||
|
c: 2
|
||||||
|
field: deleteMe
|
||||||
|
</code></pre>
|
||||||
|
|
||||||
|
<p>then</p>
|
||||||
|
<pre><code class="bash">yq w -d1 sample.yaml field
|
||||||
|
</code></pre>
|
||||||
|
|
||||||
|
<p>will output:</p>
|
||||||
|
<pre><code class="yaml">something: else
|
||||||
|
field: leaveMe
|
||||||
|
---
|
||||||
|
b:
|
||||||
|
c: 2
|
||||||
|
</code></pre>
|
||||||
|
|
||||||
|
<h3 id="multiple-documents-delete-from-all-documents">Multiple Documents - delete from all documents<a class="headerlink" href="#multiple-documents-delete-from-all-documents" title="Permanent link">¶</a></h3>
|
||||||
|
<p>Given a sample.yaml file of:</p>
|
||||||
|
<pre><code class="yaml">something: else
|
||||||
|
field: deleteMe
|
||||||
|
---
|
||||||
|
b:
|
||||||
|
c: 2
|
||||||
|
field: deleteMeToo
|
||||||
|
</code></pre>
|
||||||
|
|
||||||
|
<p>then</p>
|
||||||
|
<pre><code class="bash">yq w -d'*' sample.yaml field
|
||||||
|
</code></pre>
|
||||||
|
|
||||||
|
<p>will output:</p>
|
||||||
|
<pre><code class="yaml">something: else
|
||||||
|
---
|
||||||
|
b:
|
||||||
|
c: 2
|
||||||
|
</code></pre>
|
||||||
|
|
||||||
|
<p>Note that '*' is in quotes to avoid being interpreted by your shell.</p>
|
||||||
<h3 id="keys-with-dots">Keys with dots<a class="headerlink" href="#keys-with-dots" title="Permanent link">¶</a></h3>
|
<h3 id="keys-with-dots">Keys with dots<a class="headerlink" href="#keys-with-dots" title="Permanent link">¶</a></h3>
|
||||||
<p>When specifying a key that has a dot use key lookup indicator.</p>
|
<p>When specifying a key that has a dot use key lookup indicator.</p>
|
||||||
<pre><code class="yaml">b:
|
<pre><code class="yaml">b:
|
||||||
|
|||||||
@@ -380,7 +380,7 @@ sudo apt install yq -y
|
|||||||
</code></pre>
|
</code></pre>
|
||||||
|
|
||||||
<p>or, <a href="https://github.com/mikefarah/yq/releases/latest">Download latest binary</a> or alternatively:</p>
|
<p>or, <a href="https://github.com/mikefarah/yq/releases/latest">Download latest binary</a> or alternatively:</p>
|
||||||
<pre><code>go get github.com/mikefarah/yq
|
<pre><code>go get gopkg.in/mikefarah/yq.v2
|
||||||
</code></pre>
|
</code></pre>
|
||||||
|
|
||||||
<p><a href="https://github.com/mikefarah/yq">View on GitHub</a></p>
|
<p><a href="https://github.com/mikefarah/yq">View on GitHub</a></p>
|
||||||
|
|||||||
@@ -325,6 +325,20 @@
|
|||||||
|
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
|
<li class="md-nav__item">
|
||||||
|
<a href="#multiple-documents-merge-into-single-document" title="Multiple Documents - merge into single document" class="md-nav__link">
|
||||||
|
Multiple Documents - merge into single document
|
||||||
|
</a>
|
||||||
|
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li class="md-nav__item">
|
||||||
|
<a href="#multiple-documents-merge-into-all-documents" title="Multiple Documents - merge into all documents" class="md-nav__link">
|
||||||
|
Multiple Documents - merge into all documents
|
||||||
|
</a>
|
||||||
|
|
||||||
|
</li>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</ul>
|
</ul>
|
||||||
@@ -380,6 +394,20 @@
|
|||||||
|
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
|
<li class="md-nav__item">
|
||||||
|
<a href="#multiple-documents-merge-into-single-document" title="Multiple Documents - merge into single document" class="md-nav__link">
|
||||||
|
Multiple Documents - merge into single document
|
||||||
|
</a>
|
||||||
|
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li class="md-nav__item">
|
||||||
|
<a href="#multiple-documents-merge-into-all-documents" title="Multiple Documents - merge into all documents" class="md-nav__link">
|
||||||
|
Multiple Documents - merge into all documents
|
||||||
|
</a>
|
||||||
|
|
||||||
|
</li>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</ul>
|
</ul>
|
||||||
@@ -401,10 +429,9 @@
|
|||||||
|
|
||||||
<p>Yaml files can be merged using the 'merge' command. Each additional file merged with the first file will
|
<p>Yaml files can be merged using the 'merge' command. Each additional file merged with the first file will
|
||||||
set values for any key not existing already or where the key has no value.</p>
|
set values for any key not existing already or where the key has no value.</p>
|
||||||
<pre><code>yq m <yaml_file|json_file> <path>...
|
<pre><code>yq m <yaml_file> <path>...
|
||||||
</code></pre>
|
</code></pre>
|
||||||
|
|
||||||
<p>This command can take a json file as input too, and will output yaml unless specified to export as json (-j)</p>
|
|
||||||
<h3 id="to-stdout">To Stdout<a class="headerlink" href="#to-stdout" title="Permanent link">¶</a></h3>
|
<h3 id="to-stdout">To Stdout<a class="headerlink" href="#to-stdout" title="Permanent link">¶</a></h3>
|
||||||
<p>Given a data1.yaml file of:</p>
|
<p>Given a data1.yaml file of:</p>
|
||||||
<pre><code class="yaml">a: simple
|
<pre><code class="yaml">a: simple
|
||||||
@@ -497,6 +524,54 @@ d: false
|
|||||||
|
|
||||||
<p>Notice that 'b' does not result in the merging of the values within an array. The underlying library does not
|
<p>Notice that 'b' does not result in the merging of the values within an array. The underlying library does not
|
||||||
currently handle merging values within an array.</p>
|
currently handle merging values within an array.</p>
|
||||||
|
<h3 id="multiple-documents-merge-into-single-document">Multiple Documents - merge into single document<a class="headerlink" href="#multiple-documents-merge-into-single-document" title="Permanent link">¶</a></h3>
|
||||||
|
<p>Currently yq only has multi-document support for the <em>first</em> document being merged into. The remaining yaml files will have their first document selected.</p>
|
||||||
|
<p>Given a data1.yaml file of:</p>
|
||||||
|
<pre><code class="yaml">something: else
|
||||||
|
---
|
||||||
|
a: simple
|
||||||
|
b: cat
|
||||||
|
</code></pre>
|
||||||
|
|
||||||
|
<p>and data3.yaml file of:</p>
|
||||||
|
<pre><code class="yaml">b: dog
|
||||||
|
</code></pre>
|
||||||
|
|
||||||
|
<p>then</p>
|
||||||
|
<pre><code class="bash">yq m -x -d1 data1.yaml data3.yaml
|
||||||
|
</code></pre>
|
||||||
|
|
||||||
|
<p>will output:</p>
|
||||||
|
<pre><code class="yaml">something: else
|
||||||
|
---
|
||||||
|
a: simple
|
||||||
|
b: dog
|
||||||
|
</code></pre>
|
||||||
|
|
||||||
|
<h3 id="multiple-documents-merge-into-all-documents">Multiple Documents - merge into all documents<a class="headerlink" href="#multiple-documents-merge-into-all-documents" title="Permanent link">¶</a></h3>
|
||||||
|
<p>Currently yq only has multi-document support for the <em>first</em> document being merged into. The remaining yaml files will have their first document selected.</p>
|
||||||
|
<p>Given a data1.yaml file of:</p>
|
||||||
|
<pre><code class="yaml">something: else
|
||||||
|
---
|
||||||
|
a: simple
|
||||||
|
b: cat
|
||||||
|
</code></pre>
|
||||||
|
|
||||||
|
<p>and data3.yaml file of:</p>
|
||||||
|
<pre><code class="yaml">b: dog
|
||||||
|
</code></pre>
|
||||||
|
|
||||||
|
<p>then</p>
|
||||||
|
<pre><code class="bash">yq m -x -d'*' data1.yaml data3.yaml
|
||||||
|
</code></pre>
|
||||||
|
|
||||||
|
<p>will output:</p>
|
||||||
|
<pre><code class="yaml">b: dog
|
||||||
|
something: else
|
||||||
|
---
|
||||||
|
a: simple
|
||||||
|
b: dog
|
||||||
|
</code></pre>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -256,6 +256,13 @@
|
|||||||
Splat
|
Splat
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li class="md-nav__item">
|
||||||
|
<a href="#multiple-documents" title="Multiple Documents" class="md-nav__link">
|
||||||
|
Multiple Documents
|
||||||
|
</a>
|
||||||
|
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
<li class="md-nav__item">
|
<li class="md-nav__item">
|
||||||
@@ -385,6 +392,13 @@
|
|||||||
Splat
|
Splat
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li class="md-nav__item">
|
||||||
|
<a href="#multiple-documents" title="Multiple Documents" class="md-nav__link">
|
||||||
|
Multiple Documents
|
||||||
|
</a>
|
||||||
|
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
<li class="md-nav__item">
|
<li class="md-nav__item">
|
||||||
@@ -467,6 +481,19 @@ bob:
|
|||||||
- apples
|
- apples
|
||||||
</code></pre>
|
</code></pre>
|
||||||
|
|
||||||
|
<h3 id="multiple-documents">Multiple Documents<a class="headerlink" href="#multiple-documents" title="Permanent link">¶</a></h3>
|
||||||
|
<p>Given a sample.yaml file of:</p>
|
||||||
|
<pre><code class="yaml">something: else
|
||||||
|
---
|
||||||
|
b:
|
||||||
|
c: 2
|
||||||
|
</code></pre>
|
||||||
|
|
||||||
|
<p>then</p>
|
||||||
|
<pre><code class="bash">yq r -d1 sample.yaml b.c
|
||||||
|
</code></pre>
|
||||||
|
|
||||||
|
<p>will output the value of '2'.</p>
|
||||||
<h3 id="arrays">Arrays<a class="headerlink" href="#arrays" title="Permanent link">¶</a></h3>
|
<h3 id="arrays">Arrays<a class="headerlink" href="#arrays" title="Permanent link">¶</a></h3>
|
||||||
<p>You can give an index to access a specific element:
|
<p>You can give an index to access a specific element:
|
||||||
e.g.: given a sample file of</p>
|
e.g.: given a sample file of</p>
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
"docs": [
|
"docs": [
|
||||||
{
|
{
|
||||||
"location": "/",
|
"location": "/",
|
||||||
"text": "yq\n\u00b6\n\n\nyq is a lightweight and portable command-line YAML processor\n\n\nThe aim of the project is to be the \njq\n or sed of yaml files.\n\n\nInstall\n\u00b6\n\n\nOn MacOS:\n\n\nbrew install yq\n\n\n\n\nOn Ubuntu and other Linux distros supporting \nsnap\n packages:\n\n\nsnap install yq\n\n\n\n\nOn Ubuntu 16.04 or higher from Debian package:\n\n\nsudo add-apt-repository ppa:rmescandon/yq\nsudo apt update\nsudo apt install yq -y\n\n\n\n\nor, \nDownload latest binary\n or alternatively:\n\n\ngo get github.com/mikefarah/yq\n\n\n\n\nView on GitHub",
|
"text": "yq\n\u00b6\n\n\nyq is a lightweight and portable command-line YAML processor\n\n\nThe aim of the project is to be the \njq\n or sed of yaml files.\n\n\nInstall\n\u00b6\n\n\nOn MacOS:\n\n\nbrew install yq\n\n\n\n\nOn Ubuntu and other Linux distros supporting \nsnap\n packages:\n\n\nsnap install yq\n\n\n\n\nOn Ubuntu 16.04 or higher from Debian package:\n\n\nsudo add-apt-repository ppa:rmescandon/yq\nsudo apt update\nsudo apt install yq -y\n\n\n\n\nor, \nDownload latest binary\n or alternatively:\n\n\ngo get gopkg.in/mikefarah/yq.v2\n\n\n\n\nView on GitHub",
|
||||||
"title": "Install"
|
"title": "Install"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -12,12 +12,12 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"location": "/#install",
|
"location": "/#install",
|
||||||
"text": "On MacOS: brew install yq On Ubuntu and other Linux distros supporting snap packages: snap install yq On Ubuntu 16.04 or higher from Debian package: sudo add-apt-repository ppa:rmescandon/yq\nsudo apt update\nsudo apt install yq -y or, Download latest binary or alternatively: go get github.com/mikefarah/yq View on GitHub",
|
"text": "On MacOS: brew install yq On Ubuntu and other Linux distros supporting snap packages: snap install yq On Ubuntu 16.04 or higher from Debian package: sudo add-apt-repository ppa:rmescandon/yq\nsudo apt update\nsudo apt install yq -y or, Download latest binary or alternatively: go get gopkg.in/mikefarah/yq.v2 View on GitHub",
|
||||||
"title": "Install"
|
"title": "Install"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"location": "/read/",
|
"location": "/read/",
|
||||||
"text": "yq r <yaml_file|json_file> <path>\n\n\n\n\nThis command can take a json file as input too, and will output yaml unless specified to export as json (-j)\n\n\nBasic\n\u00b6\n\n\nGiven a sample.yaml file of:\n\n\nb:\n c: 2\n\n\n\n\nthen\n\n\nyq r sample.yaml b.c\n\n\n\n\nwill output the value of '2'.\n\n\nFrom Stdin\n\u00b6\n\n\nGiven a sample.yaml file of:\n\n\ncat sample.yaml | yq r - b.c\n\n\n\n\nwill output the value of '2'.\n\n\nSplat\n\u00b6\n\n\nGiven a sample.yaml file of:\n\n\n---\nbob:\n item1:\n cats: bananas\n item2:\n cats: apples\n\n\n\n\nthen\n\n\nyq r sample.yaml bob.*.cats\n\n\n\n\nwill output\n\n\n- bananas\n- apples\n\n\n\n\nArrays\n\u00b6\n\n\nYou can give an index to access a specific element:\ne.g.: given a sample file of\n\n\nb:\n e:\n - name: fred\n value: 3\n - name: sam\n value: 4\n\n\n\n\nthen\n\n\nyq r sample.yaml 'b.e[1].name'\n\n\n\n\nwill output 'sam'\n\n\nNote that the path is in quotes to avoid the square brackets being interpreted by your shell.\n\n\nArray Splat\n\u00b6\n\n\ne.g.: given a sample file of\n\n\nb:\n e:\n - name: fred\n value: 3\n - name: sam\n value: 4\n\n\n\n\nthen\n\n\nyq r sample.yaml 'b.e[*].name'\n\n\n\n\nwill output:\n\n\n- fred\n- sam\n\n\n\n\nNote that the path is in quotes to avoid the square brackets being interpreted by your shell.\n\n\nKeys with dots\n\u00b6\n\n\nWhen specifying a key that has a dot use key lookup indicator.\n\n\nb:\n foo.bar: 7\n\n\n\n\nyaml r sample.yaml 'b[foo.bar]'\n\n\n\n\nyaml w sample.yaml 'b[foo.bar]' 9\n\n\n\n\nAny valid yaml key can be specified as part of a key lookup.\n\n\nNote that the path is in quotes to avoid the square brackets being interpreted by your shell.",
|
"text": "yq r <yaml_file|json_file> <path>\n\n\n\n\nThis command can take a json file as input too, and will output yaml unless specified to export as json (-j)\n\n\nBasic\n\u00b6\n\n\nGiven a sample.yaml file of:\n\n\nb:\n c: 2\n\n\n\n\nthen\n\n\nyq r sample.yaml b.c\n\n\n\n\nwill output the value of '2'.\n\n\nFrom Stdin\n\u00b6\n\n\nGiven a sample.yaml file of:\n\n\ncat sample.yaml | yq r - b.c\n\n\n\n\nwill output the value of '2'.\n\n\nSplat\n\u00b6\n\n\nGiven a sample.yaml file of:\n\n\n---\nbob:\n item1:\n cats: bananas\n item2:\n cats: apples\n\n\n\n\nthen\n\n\nyq r sample.yaml bob.*.cats\n\n\n\n\nwill output\n\n\n- bananas\n- apples\n\n\n\n\nMultiple Documents\n\u00b6\n\n\nGiven a sample.yaml file of:\n\n\nsomething: else\n---\nb:\n c: 2\n\n\n\n\nthen\n\n\nyq r -d1 sample.yaml b.c\n\n\n\n\nwill output the value of '2'.\n\n\nArrays\n\u00b6\n\n\nYou can give an index to access a specific element:\ne.g.: given a sample file of\n\n\nb:\n e:\n - name: fred\n value: 3\n - name: sam\n value: 4\n\n\n\n\nthen\n\n\nyq r sample.yaml 'b.e[1].name'\n\n\n\n\nwill output 'sam'\n\n\nNote that the path is in quotes to avoid the square brackets being interpreted by your shell.\n\n\nArray Splat\n\u00b6\n\n\ne.g.: given a sample file of\n\n\nb:\n e:\n - name: fred\n value: 3\n - name: sam\n value: 4\n\n\n\n\nthen\n\n\nyq r sample.yaml 'b.e[*].name'\n\n\n\n\nwill output:\n\n\n- fred\n- sam\n\n\n\n\nNote that the path is in quotes to avoid the square brackets being interpreted by your shell.\n\n\nKeys with dots\n\u00b6\n\n\nWhen specifying a key that has a dot use key lookup indicator.\n\n\nb:\n foo.bar: 7\n\n\n\n\nyaml r sample.yaml 'b[foo.bar]'\n\n\n\n\nyaml w sample.yaml 'b[foo.bar]' 9\n\n\n\n\nAny valid yaml key can be specified as part of a key lookup.\n\n\nNote that the path is in quotes to avoid the square brackets being interpreted by your shell.",
|
||||||
"title": "Read"
|
"title": "Read"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -35,6 +35,11 @@
|
|||||||
"text": "Given a sample.yaml file of: ---\nbob:\n item1:\n cats: bananas\n item2:\n cats: apples then yq r sample.yaml bob.*.cats will output - bananas\n- apples",
|
"text": "Given a sample.yaml file of: ---\nbob:\n item1:\n cats: bananas\n item2:\n cats: apples then yq r sample.yaml bob.*.cats will output - bananas\n- apples",
|
||||||
"title": "Splat"
|
"title": "Splat"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"location": "/read/#multiple-documents",
|
||||||
|
"text": "Given a sample.yaml file of: something: else\n---\nb:\n c: 2 then yq r -d1 sample.yaml b.c will output the value of '2'.",
|
||||||
|
"title": "Multiple Documents"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"location": "/read/#arrays",
|
"location": "/read/#arrays",
|
||||||
"text": "You can give an index to access a specific element:\ne.g.: given a sample file of b:\n e:\n - name: fred\n value: 3\n - name: sam\n value: 4 then yq r sample.yaml 'b.e[1].name' will output 'sam' Note that the path is in quotes to avoid the square brackets being interpreted by your shell.",
|
"text": "You can give an index to access a specific element:\ne.g.: given a sample file of b:\n e:\n - name: fred\n value: 3\n - name: sam\n value: 4 then yq r sample.yaml 'b.e[1].name' will output 'sam' Note that the path is in quotes to avoid the square brackets being interpreted by your shell.",
|
||||||
@@ -52,7 +57,7 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"location": "/write/",
|
"location": "/write/",
|
||||||
"text": "yq w <yaml_file|json_file> <path> <new value>\n\n\n\n\nThis command can take a json file as input too, and will output yaml unless specified to export as json (-j)\n\n\nTo Stdout\n\u00b6\n\n\nGiven a sample.yaml file of:\n\n\nb:\n c: 2\n\n\n\n\nthen\n\n\nyq w sample.yaml b.c cat\n\n\n\n\nwill output:\n\n\nb:\n c: cat\n\n\n\n\nFrom STDIN\n\u00b6\n\n\ncat sample.yaml | yq w - b.c blah\n\n\n\n\nAdding new fields\n\u00b6\n\n\nAny missing fields in the path will be created on the fly.\n\n\nGiven a sample.yaml file of:\n\n\nb:\n c: 2\n\n\n\n\nthen\n\n\nyq w sample.yaml b.d[0] \"new thing\"\n\n\n\n\nwill output:\n\n\nb:\n c: cat\n d:\n - new thing\n\n\n\n\nAppending value to an array field\n\u00b6\n\n\nGiven a sample.yaml file of:\n\n\nb:\n c: 2\n d:\n - new thing\n - foo thing\n\n\n\n\nthen\n\n\nyq w sample.yaml \"b.d[+]\" \"bar thing\"\n\n\n\n\nwill output:\n\n\nb:\n c: cat\n d:\n - new thing\n - foo thing\n - bar thing\n\n\n\n\nNote that the path is in quotes to avoid the square brackets being interpreted by your shell.\n\n\nUpdating files in-place\n\u00b6\n\n\nGiven a sample.yaml file of:\n\n\nb:\n c: 2\n\n\n\n\nthen\n\n\nyq w -i sample.yaml b.c cat\n\n\n\n\nwill update the sample.yaml file so that the value of 'c' is cat.\n\n\nUpdating multiple values with a script\n\u00b6\n\n\nGiven a sample.yaml file of:\n\n\nb:\n c: 2\n e:\n - name: Billy Bob\n\n\n\n\nand a script update_instructions.yaml of:\n\n\nb.c: 3\nb.e[0].name: Howdy Partner\n\n\n\n\nthen\n\n\nyq w -s update_instructions.yaml sample.yaml\n\n\n\n\nwill output:\n\n\nb:\n c: 3\n e:\n - name: Howdy Partner\n\n\n\n\nAnd, of course, you can pipe the instructions in using '-':\n\n\ncat update_instructions.yaml | yq w -s - sample.yaml\n\n\n\n\nValues starting with a hyphen (or dash)\n\u00b6\n\n\nThe flag terminator needs to be used to stop the app from attempting to parse the subsequent arguments as flags:\n\n\nyq w -- my.path -3\n\n\n\n\nwill output\n\n\nmy:\n path: -3\n\n\n\n\nKeys with dots\n\u00b6\n\n\nWhen specifying a key that has a dot use key lookup indicator.\n\n\nb:\n foo.bar: 7\n\n\n\n\nyaml r sample.yaml 'b[foo.bar]'\n\n\n\n\nyaml w sample.yaml 'b[foo.bar]' 9\n\n\n\n\nAny valid yaml key can be specified as part of a key lookup.\n\n\nNote that the path is in quotes to avoid the square brackets being interpreted by your shell.",
|
"text": "yq w <yaml_file> <path> <new value>\n\n\n\n\nTo Stdout\n\u00b6\n\n\nGiven a sample.yaml file of:\n\n\nb:\n c: 2\n\n\n\n\nthen\n\n\nyq w sample.yaml b.c cat\n\n\n\n\nwill output:\n\n\nb:\n c: cat\n\n\n\n\nFrom STDIN\n\u00b6\n\n\ncat sample.yaml | yq w - b.c blah\n\n\n\n\nAdding new fields\n\u00b6\n\n\nAny missing fields in the path will be created on the fly.\n\n\nGiven a sample.yaml file of:\n\n\nb:\n c: 2\n\n\n\n\nthen\n\n\nyq w sample.yaml b.d[0] \"new thing\"\n\n\n\n\nwill output:\n\n\nb:\n c: cat\n d:\n - new thing\n\n\n\n\nAppending value to an array field\n\u00b6\n\n\nGiven a sample.yaml file of:\n\n\nb:\n c: 2\n d:\n - new thing\n - foo thing\n\n\n\n\nthen\n\n\nyq w sample.yaml \"b.d[+]\" \"bar thing\"\n\n\n\n\nwill output:\n\n\nb:\n c: cat\n d:\n - new thing\n - foo thing\n - bar thing\n\n\n\n\nNote that the path is in quotes to avoid the square brackets being interpreted by your shell.\n\n\nMultiple Documents - update a single document\n\u00b6\n\n\nGiven a sample.yaml file of:\n\n\nsomething: else\n---\nb:\n c: 2\n\n\n\n\nthen\n\n\nyq w -d1 sample.yaml b.c 5\n\n\n\n\nwill output:\n\n\nsomething: else\n---\nb:\n c: 5\n\n\n\n\nMultiple Documents - update all documents\n\u00b6\n\n\nGiven a sample.yaml file of:\n\n\nsomething: else\n---\nb:\n c: 2\n\n\n\n\nthen\n\n\nyq w -d'*' sample.yaml b.c 5\n\n\n\n\nwill output:\n\n\nsomething: else\nb:\n c: 5\n---\nb:\n c: 5\n\n\n\n\nNote that '*' is in quotes to avoid being interpreted by your shell.\n\n\nUpdating files in-place\n\u00b6\n\n\nGiven a sample.yaml file of:\n\n\nb:\n c: 2\n\n\n\n\nthen\n\n\nyq w -i sample.yaml b.c cat\n\n\n\n\nwill update the sample.yaml file so that the value of 'c' is cat.\n\n\nUpdating multiple values with a script\n\u00b6\n\n\nGiven a sample.yaml file of:\n\n\nb:\n c: 2\n e:\n - name: Billy Bob\n\n\n\n\nand a script update_instructions.yaml of:\n\n\nb.c: 3\nb.e[0].name: Howdy Partner\n\n\n\n\nthen\n\n\nyq w -s update_instructions.yaml sample.yaml\n\n\n\n\nwill output:\n\n\nb:\n c: 3\n e:\n - name: Howdy Partner\n\n\n\n\nAnd, of course, you can pipe the instructions in using '-':\n\n\ncat update_instructions.yaml | yq w -s - sample.yaml\n\n\n\n\nValues starting with a hyphen (or dash)\n\u00b6\n\n\nThe flag terminator needs to be used to stop the app from attempting to parse the subsequent arguments as flags:\n\n\nyq w -- my.path -3\n\n\n\n\nwill output\n\n\nmy:\n path: -3\n\n\n\n\nKeys with dots\n\u00b6\n\n\nWhen specifying a key that has a dot use key lookup indicator.\n\n\nb:\n foo.bar: 7\n\n\n\n\nyaml r sample.yaml 'b[foo.bar]'\n\n\n\n\nyaml w sample.yaml 'b[foo.bar]' 9\n\n\n\n\nAny valid yaml key can be specified as part of a key lookup.\n\n\nNote that the path is in quotes to avoid the square brackets being interpreted by your shell.",
|
||||||
"title": "Write/Update"
|
"title": "Write/Update"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -75,6 +80,16 @@
|
|||||||
"text": "Given a sample.yaml file of: b:\n c: 2\n d:\n - new thing\n - foo thing then yq w sample.yaml \"b.d[+]\" \"bar thing\" will output: b:\n c: cat\n d:\n - new thing\n - foo thing\n - bar thing Note that the path is in quotes to avoid the square brackets being interpreted by your shell.",
|
"text": "Given a sample.yaml file of: b:\n c: 2\n d:\n - new thing\n - foo thing then yq w sample.yaml \"b.d[+]\" \"bar thing\" will output: b:\n c: cat\n d:\n - new thing\n - foo thing\n - bar thing Note that the path is in quotes to avoid the square brackets being interpreted by your shell.",
|
||||||
"title": "Appending value to an array field"
|
"title": "Appending value to an array field"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"location": "/write/#multiple-documents-update-a-single-document",
|
||||||
|
"text": "Given a sample.yaml file of: something: else\n---\nb:\n c: 2 then yq w -d1 sample.yaml b.c 5 will output: something: else\n---\nb:\n c: 5",
|
||||||
|
"title": "Multiple Documents - update a single document"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"location": "/write/#multiple-documents-update-all-documents",
|
||||||
|
"text": "Given a sample.yaml file of: something: else\n---\nb:\n c: 2 then yq w -d'*' sample.yaml b.c 5 will output: something: else\nb:\n c: 5\n---\nb:\n c: 5 Note that '*' is in quotes to avoid being interpreted by your shell.",
|
||||||
|
"title": "Multiple Documents - update all documents"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"location": "/write/#updating-files-in-place",
|
"location": "/write/#updating-files-in-place",
|
||||||
"text": "Given a sample.yaml file of: b:\n c: 2 then yq w -i sample.yaml b.c cat will update the sample.yaml file so that the value of 'c' is cat.",
|
"text": "Given a sample.yaml file of: b:\n c: 2 then yq w -i sample.yaml b.c cat will update the sample.yaml file so that the value of 'c' is cat.",
|
||||||
@@ -97,7 +112,7 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"location": "/delete/",
|
"location": "/delete/",
|
||||||
"text": "yq d <yaml_file|json_file> <path_to_delete>\n\n\n\n\nThis command can take a json file as input too, and will output yaml unless specified to export as json (-j)\n\n\nTo Stdout\n\u00b6\n\n\nGiven a sample.yaml file of:\n\n\nb:\n c: 2\n apples: green\n\n\n\n\nthen\n\n\nyq d sample.yaml b.c\n\n\n\n\nwill output:\n\n\nb:\n apples: green\n\n\n\n\nFrom STDIN\n\u00b6\n\n\ncat sample.yaml | yq d - b.c\n\n\n\n\nDeleting array elements\n\u00b6\n\n\nGiven a sample.yaml file of:\n\n\nb:\n c: \n - 1\n - 2\n - 3\n\n\n\n\nthen\n\n\nyq d sample.yaml 'b.c[1]'\n\n\n\n\nwill output:\n\n\nb:\n c:\n - 1\n - 3\n\n\n\n\nDeleting nodes in-place\n\u00b6\n\n\nGiven a sample.yaml file of:\n\n\nb:\n c: 2\n apples: green\n\n\n\n\nthen\n\n\nyq d -i sample.yaml b.c\n\n\n\n\nwill update the sample.yaml file so that the 'c' node is deleted\n\n\nKeys with dots\n\u00b6\n\n\nWhen specifying a key that has a dot use key lookup indicator.\n\n\nb:\n foo.bar: 7\n\n\n\n\nyaml r sample.yaml 'b[foo.bar]'\n\n\n\n\nyaml w sample.yaml 'b[foo.bar]' 9\n\n\n\n\nAny valid yaml key can be specified as part of a key lookup.\n\n\nNote that the path is in quotes to avoid the square brackets being interpreted by your shell.",
|
"text": "yq d <yaml_file> <path_to_delete>\n\n\n\n\nTo Stdout\n\u00b6\n\n\nGiven a sample.yaml file of:\n\n\nb:\n c: 2\n apples: green\n\n\n\n\nthen\n\n\nyq d sample.yaml b.c\n\n\n\n\nwill output:\n\n\nb:\n apples: green\n\n\n\n\nFrom STDIN\n\u00b6\n\n\ncat sample.yaml | yq d - b.c\n\n\n\n\nDeleting array elements\n\u00b6\n\n\nGiven a sample.yaml file of:\n\n\nb:\n c: \n - 1\n - 2\n - 3\n\n\n\n\nthen\n\n\nyq d sample.yaml 'b.c[1]'\n\n\n\n\nwill output:\n\n\nb:\n c:\n - 1\n - 3\n\n\n\n\nDeleting nodes in-place\n\u00b6\n\n\nGiven a sample.yaml file of:\n\n\nb:\n c: 2\n apples: green\n\n\n\n\nthen\n\n\nyq d -i sample.yaml b.c\n\n\n\n\nwill update the sample.yaml file so that the 'c' node is deleted\n\n\nMultiple Documents - delete from single document\n\u00b6\n\n\nGiven a sample.yaml file of:\n\n\nsomething: else\nfield: leaveMe\n---\nb:\n c: 2\nfield: deleteMe\n\n\n\n\nthen\n\n\nyq w -d1 sample.yaml field\n\n\n\n\nwill output:\n\n\nsomething: else\nfield: leaveMe\n---\nb:\n c: 2\n\n\n\n\nMultiple Documents - delete from all documents\n\u00b6\n\n\nGiven a sample.yaml file of:\n\n\nsomething: else\nfield: deleteMe\n---\nb:\n c: 2\nfield: deleteMeToo\n\n\n\n\nthen\n\n\nyq w -d'*' sample.yaml field\n\n\n\n\nwill output:\n\n\nsomething: else\n---\nb:\n c: 2\n\n\n\n\nNote that '*' is in quotes to avoid being interpreted by your shell.\n\n\nKeys with dots\n\u00b6\n\n\nWhen specifying a key that has a dot use key lookup indicator.\n\n\nb:\n foo.bar: 7\n\n\n\n\nyaml r sample.yaml 'b[foo.bar]'\n\n\n\n\nyaml w sample.yaml 'b[foo.bar]' 9\n\n\n\n\nAny valid yaml key can be specified as part of a key lookup.\n\n\nNote that the path is in quotes to avoid the square brackets being interpreted by your shell.",
|
||||||
"title": "Delete"
|
"title": "Delete"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -120,6 +135,16 @@
|
|||||||
"text": "Given a sample.yaml file of: b:\n c: 2\n apples: green then yq d -i sample.yaml b.c will update the sample.yaml file so that the 'c' node is deleted",
|
"text": "Given a sample.yaml file of: b:\n c: 2\n apples: green then yq d -i sample.yaml b.c will update the sample.yaml file so that the 'c' node is deleted",
|
||||||
"title": "Deleting nodes in-place"
|
"title": "Deleting nodes in-place"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"location": "/delete/#multiple-documents-delete-from-single-document",
|
||||||
|
"text": "Given a sample.yaml file of: something: else\nfield: leaveMe\n---\nb:\n c: 2\nfield: deleteMe then yq w -d1 sample.yaml field will output: something: else\nfield: leaveMe\n---\nb:\n c: 2",
|
||||||
|
"title": "Multiple Documents - delete from single document"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"location": "/delete/#multiple-documents-delete-from-all-documents",
|
||||||
|
"text": "Given a sample.yaml file of: something: else\nfield: deleteMe\n---\nb:\n c: 2\nfield: deleteMeToo then yq w -d'*' sample.yaml field will output: something: else\n---\nb:\n c: 2 Note that '*' is in quotes to avoid being interpreted by your shell.",
|
||||||
|
"title": "Multiple Documents - delete from all documents"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"location": "/delete/#keys-with-dots",
|
"location": "/delete/#keys-with-dots",
|
||||||
"text": "When specifying a key that has a dot use key lookup indicator. b:\n foo.bar: 7 yaml r sample.yaml 'b[foo.bar]' yaml w sample.yaml 'b[foo.bar]' 9 Any valid yaml key can be specified as part of a key lookup. Note that the path is in quotes to avoid the square brackets being interpreted by your shell.",
|
"text": "When specifying a key that has a dot use key lookup indicator. b:\n foo.bar: 7 yaml r sample.yaml 'b[foo.bar]' yaml w sample.yaml 'b[foo.bar]' 9 Any valid yaml key can be specified as part of a key lookup. Note that the path is in quotes to avoid the square brackets being interpreted by your shell.",
|
||||||
@@ -127,7 +152,7 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"location": "/create/",
|
"location": "/create/",
|
||||||
"text": "Yaml files can be created using the 'new' command. This works in the same way as the write command, but you don't pass in an existing Yaml file.\n\n\nyq n <path> <new value>\n\n\n\n\nCreating a simple yaml file\n\u00b6\n\n\nyq n b.c cat\n\n\n\n\nwill output:\n\n\nb:\n c: cat\n\n\n\n\nCreating using a create script\n\u00b6\n\n\nCreate scripts follow the same format as the update scripts.\n\n\nGiven a script create_instructions.yaml of:\n\n\nb.c: 3\nb.e[0].name: Howdy Partner\n\n\n\n\nthen\n\n\nyq n -s create_instructions.yaml\n\n\n\n\nwill output:\n\n\nb:\n c: 3\n e:\n - name: Howdy Partner\n\n\n\n\nYou can also pipe the instructions in:\n\n\ncat create_instructions.yaml | yq n -s -\n\n\n\n\nKeys with dots\n\u00b6\n\n\nWhen specifying a key that has a dot use key lookup indicator.\n\n\nb:\n foo.bar: 7\n\n\n\n\nyaml r sample.yaml 'b[foo.bar]'\n\n\n\n\nyaml w sample.yaml 'b[foo.bar]' 9\n\n\n\n\nAny valid yaml key can be specified as part of a key lookup.\n\n\nNote that the path is in quotes to avoid the square brackets being interpreted by your shell.",
|
"text": "Yaml files can be created using the 'new' command. This works in the same way as the write command, but you don't pass in an existing Yaml file. Currently this does not support creating multiple documents in a single yaml file.\n\n\nyq n <path> <new value>\n\n\n\n\nCreating a simple yaml file\n\u00b6\n\n\nyq n b.c cat\n\n\n\n\nwill output:\n\n\nb:\n c: cat\n\n\n\n\nCreating using a create script\n\u00b6\n\n\nCreate scripts follow the same format as the update scripts.\n\n\nGiven a script create_instructions.yaml of:\n\n\nb.c: 3\nb.e[0].name: Howdy Partner\n\n\n\n\nthen\n\n\nyq n -s create_instructions.yaml\n\n\n\n\nwill output:\n\n\nb:\n c: 3\n e:\n - name: Howdy Partner\n\n\n\n\nYou can also pipe the instructions in:\n\n\ncat create_instructions.yaml | yq n -s -\n\n\n\n\nKeys with dots\n\u00b6\n\n\nWhen specifying a key that has a dot use key lookup indicator.\n\n\nb:\n foo.bar: 7\n\n\n\n\nyaml r sample.yaml 'b[foo.bar]'\n\n\n\n\nyaml w sample.yaml 'b[foo.bar]' 9\n\n\n\n\nAny valid yaml key can be specified as part of a key lookup.\n\n\nNote that the path is in quotes to avoid the square brackets being interpreted by your shell.",
|
||||||
"title": "Create"
|
"title": "Create"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -147,12 +172,12 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"location": "/convert/",
|
"location": "/convert/",
|
||||||
"text": "Yaml to Json\n\u00b6\n\n\nTo convert output to json, use the --tojson (or -j) flag. This can be used with any command.\n\n\nGiven a sample.yaml file of:\n\n\nb:\n c: 2\n\n\n\n\nthen\n\n\nyq r -j sample.yaml b.c\n\n\n\n\nwill output\n\n\n{\"b\":{\"c\":2}}\n\n\n\n\nJson to Yaml\n\u00b6\n\n\nTo read in json, just pass in a json file instead of yaml, it will just work :)\n\n\ne.g given a json file\n\n\n{\"a\":\"Easy! as one two three\",\"b\":{\"c\":2,\"d\":[3,4]}}\n\n\n\n\nthen\n\n\nyq r sample.json\n\n\n\n\nwill output\n\n\na: Easy! as one two three\nb:\n c: 2\n d:\n - 3\n - 4",
|
"text": "Yaml to Json\n\u00b6\n\n\nTo convert output to json, use the --tojson (or -j) flag. This can only be used with the read command.\n\n\nGiven a sample.yaml file of:\n\n\nb:\n c: 2\n\n\n\n\nthen\n\n\nyq r -j sample.yaml b.c\n\n\n\n\nwill output\n\n\n{\"b\":{\"c\":2}}\n\n\n\n\nJson to Yaml\n\u00b6\n\n\nTo read in json, just pass in a json file instead of yaml, it will just work :)\n\n\ne.g given a json file\n\n\n{\"a\":\"Easy! as one two three\",\"b\":{\"c\":2,\"d\":[3,4]}}\n\n\n\n\nthen\n\n\nyq r sample.json\n\n\n\n\nwill output\n\n\na: Easy! as one two three\nb:\n c: 2\n d:\n - 3\n - 4",
|
||||||
"title": "Convert"
|
"title": "Convert"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"location": "/convert/#yaml-to-json",
|
"location": "/convert/#yaml-to-json",
|
||||||
"text": "To convert output to json, use the --tojson (or -j) flag. This can be used with any command. Given a sample.yaml file of: b:\n c: 2 then yq r -j sample.yaml b.c will output {\"b\":{\"c\":2}}",
|
"text": "To convert output to json, use the --tojson (or -j) flag. This can only be used with the read command. Given a sample.yaml file of: b:\n c: 2 then yq r -j sample.yaml b.c will output {\"b\":{\"c\":2}}",
|
||||||
"title": "Yaml to Json"
|
"title": "Yaml to Json"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -162,7 +187,7 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"location": "/merge/",
|
"location": "/merge/",
|
||||||
"text": "Yaml files can be merged using the 'merge' command. Each additional file merged with the first file will\nset values for any key not existing already or where the key has no value.\n\n\nyq m <yaml_file|json_file> <path>...\n\n\n\n\nThis command can take a json file as input too, and will output yaml unless specified to export as json (-j)\n\n\nTo Stdout\n\u00b6\n\n\nGiven a data1.yaml file of:\n\n\na: simple\nb: [1, 2]\n\n\n\n\nand data2.yaml file of:\n\n\na: other\nc:\n test: 1\n\n\n\n\nthen\n\n\nyq m data1.yaml data2.yaml\n\n\n\n\nwill output:\n\n\na: simple\nb: [1, 2]\nc:\n test: 1\n\n\n\n\nUpdating files in-place\n\u00b6\n\n\nGiven a data1.yaml file of:\n\n\na: simple\nb: [1, 2]\n\n\n\n\nand data2.yaml file of:\n\n\na: other\nc:\n test: 1\n\n\n\n\nthen\n\n\nyq m -i data1.yaml data2.yaml\n\n\n\n\nwill update the data1.yaml file so that the value of 'c' is 'test: 1'.\n\n\nOverwrite values\n\u00b6\n\n\nGiven a data1.yaml file of:\n\n\na: simple\nb: [1, 2]\n\n\n\n\nand data2.yaml file of:\n\n\na: other\nc:\n test: 1\n\n\n\n\nthen\n\n\nyq m -x data1.yaml data2.yaml\n\n\n\n\nwill output:\n\n\na: other\nb: [1, 2]\nc:\n test: 1\n\n\n\n\nOverwrite values with arrays\n\u00b6\n\n\nGiven a data1.yaml file of:\n\n\na: simple\nb: [1, 2]\n\n\n\n\nand data3.yaml file of:\n\n\nb: [2, 3, 4]\nc:\n test: 2\n other: true\nd: false\n\n\n\n\nthen\n\n\nyq m -x data1.yaml data3.yaml\n\n\n\n\nwill output:\n\n\na: simple\nb: [2, 3, 4]\nc:\n test: 2\n other: true\nd: false\n\n\n\n\nNotice that 'b' does not result in the merging of the values within an array. The underlying library does not\ncurrently handle merging values within an array.",
|
"text": "Yaml files can be merged using the 'merge' command. Each additional file merged with the first file will\nset values for any key not existing already or where the key has no value.\n\n\nyq m <yaml_file> <path>...\n\n\n\n\nTo Stdout\n\u00b6\n\n\nGiven a data1.yaml file of:\n\n\na: simple\nb: [1, 2]\n\n\n\n\nand data2.yaml file of:\n\n\na: other\nc:\n test: 1\n\n\n\n\nthen\n\n\nyq m data1.yaml data2.yaml\n\n\n\n\nwill output:\n\n\na: simple\nb: [1, 2]\nc:\n test: 1\n\n\n\n\nUpdating files in-place\n\u00b6\n\n\nGiven a data1.yaml file of:\n\n\na: simple\nb: [1, 2]\n\n\n\n\nand data2.yaml file of:\n\n\na: other\nc:\n test: 1\n\n\n\n\nthen\n\n\nyq m -i data1.yaml data2.yaml\n\n\n\n\nwill update the data1.yaml file so that the value of 'c' is 'test: 1'.\n\n\nOverwrite values\n\u00b6\n\n\nGiven a data1.yaml file of:\n\n\na: simple\nb: [1, 2]\n\n\n\n\nand data2.yaml file of:\n\n\na: other\nc:\n test: 1\n\n\n\n\nthen\n\n\nyq m -x data1.yaml data2.yaml\n\n\n\n\nwill output:\n\n\na: other\nb: [1, 2]\nc:\n test: 1\n\n\n\n\nOverwrite values with arrays\n\u00b6\n\n\nGiven a data1.yaml file of:\n\n\na: simple\nb: [1, 2]\n\n\n\n\nand data3.yaml file of:\n\n\nb: [2, 3, 4]\nc:\n test: 2\n other: true\nd: false\n\n\n\n\nthen\n\n\nyq m -x data1.yaml data3.yaml\n\n\n\n\nwill output:\n\n\na: simple\nb: [2, 3, 4]\nc:\n test: 2\n other: true\nd: false\n\n\n\n\nNotice that 'b' does not result in the merging of the values within an array. The underlying library does not\ncurrently handle merging values within an array.\n\n\nMultiple Documents - merge into single document\n\u00b6\n\n\nCurrently yq only has multi-document support for the \nfirst\n document being merged into. The remaining yaml files will have their first document selected.\n\n\nGiven a data1.yaml file of:\n\n\nsomething: else\n---\na: simple\nb: cat\n\n\n\n\nand data3.yaml file of:\n\n\nb: dog\n\n\n\n\nthen\n\n\nyq m -x -d1 data1.yaml data3.yaml\n\n\n\n\nwill output:\n\n\nsomething: else\n---\na: simple\nb: dog\n\n\n\n\nMultiple Documents - merge into all documents\n\u00b6\n\n\nCurrently yq only has multi-document support for the \nfirst\n document being merged into. The remaining yaml files will have their first document selected.\n\n\nGiven a data1.yaml file of:\n\n\nsomething: else\n---\na: simple\nb: cat\n\n\n\n\nand data3.yaml file of:\n\n\nb: dog\n\n\n\n\nthen\n\n\nyq m -x -d'*' data1.yaml data3.yaml\n\n\n\n\nwill output:\n\n\nb: dog\nsomething: else\n---\na: simple\nb: dog",
|
||||||
"title": "Merge"
|
"title": "Merge"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -184,6 +209,16 @@
|
|||||||
"location": "/merge/#overwrite-values-with-arrays",
|
"location": "/merge/#overwrite-values-with-arrays",
|
||||||
"text": "Given a data1.yaml file of: a: simple\nb: [1, 2] and data3.yaml file of: b: [2, 3, 4]\nc:\n test: 2\n other: true\nd: false then yq m -x data1.yaml data3.yaml will output: a: simple\nb: [2, 3, 4]\nc:\n test: 2\n other: true\nd: false Notice that 'b' does not result in the merging of the values within an array. The underlying library does not\ncurrently handle merging values within an array.",
|
"text": "Given a data1.yaml file of: a: simple\nb: [1, 2] and data3.yaml file of: b: [2, 3, 4]\nc:\n test: 2\n other: true\nd: false then yq m -x data1.yaml data3.yaml will output: a: simple\nb: [2, 3, 4]\nc:\n test: 2\n other: true\nd: false Notice that 'b' does not result in the merging of the values within an array. The underlying library does not\ncurrently handle merging values within an array.",
|
||||||
"title": "Overwrite values with arrays"
|
"title": "Overwrite values with arrays"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"location": "/merge/#multiple-documents-merge-into-single-document",
|
||||||
|
"text": "Currently yq only has multi-document support for the first document being merged into. The remaining yaml files will have their first document selected. Given a data1.yaml file of: something: else\n---\na: simple\nb: cat and data3.yaml file of: b: dog then yq m -x -d1 data1.yaml data3.yaml will output: something: else\n---\na: simple\nb: dog",
|
||||||
|
"title": "Multiple Documents - merge into single document"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"location": "/merge/#multiple-documents-merge-into-all-documents",
|
||||||
|
"text": "Currently yq only has multi-document support for the first document being merged into. The remaining yaml files will have their first document selected. Given a data1.yaml file of: something: else\n---\na: simple\nb: cat and data3.yaml file of: b: dog then yq m -x -d'*' data1.yaml data3.yaml will output: b: dog\nsomething: else\n---\na: simple\nb: dog",
|
||||||
|
"title": "Multiple Documents - merge into all documents"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
<url>
|
<url>
|
||||||
<loc>/</loc>
|
<loc>/</loc>
|
||||||
<lastmod>2018-06-12</lastmod>
|
<lastmod>2018-06-20</lastmod>
|
||||||
<changefreq>daily</changefreq>
|
<changefreq>daily</changefreq>
|
||||||
</url>
|
</url>
|
||||||
|
|
||||||
@@ -12,7 +12,7 @@
|
|||||||
|
|
||||||
<url>
|
<url>
|
||||||
<loc>/read/</loc>
|
<loc>/read/</loc>
|
||||||
<lastmod>2018-06-12</lastmod>
|
<lastmod>2018-06-20</lastmod>
|
||||||
<changefreq>daily</changefreq>
|
<changefreq>daily</changefreq>
|
||||||
</url>
|
</url>
|
||||||
|
|
||||||
@@ -20,7 +20,7 @@
|
|||||||
|
|
||||||
<url>
|
<url>
|
||||||
<loc>/write/</loc>
|
<loc>/write/</loc>
|
||||||
<lastmod>2018-06-12</lastmod>
|
<lastmod>2018-06-20</lastmod>
|
||||||
<changefreq>daily</changefreq>
|
<changefreq>daily</changefreq>
|
||||||
</url>
|
</url>
|
||||||
|
|
||||||
@@ -28,7 +28,7 @@
|
|||||||
|
|
||||||
<url>
|
<url>
|
||||||
<loc>/delete/</loc>
|
<loc>/delete/</loc>
|
||||||
<lastmod>2018-06-12</lastmod>
|
<lastmod>2018-06-20</lastmod>
|
||||||
<changefreq>daily</changefreq>
|
<changefreq>daily</changefreq>
|
||||||
</url>
|
</url>
|
||||||
|
|
||||||
@@ -36,7 +36,7 @@
|
|||||||
|
|
||||||
<url>
|
<url>
|
||||||
<loc>/create/</loc>
|
<loc>/create/</loc>
|
||||||
<lastmod>2018-06-12</lastmod>
|
<lastmod>2018-06-20</lastmod>
|
||||||
<changefreq>daily</changefreq>
|
<changefreq>daily</changefreq>
|
||||||
</url>
|
</url>
|
||||||
|
|
||||||
@@ -44,7 +44,7 @@
|
|||||||
|
|
||||||
<url>
|
<url>
|
||||||
<loc>/convert/</loc>
|
<loc>/convert/</loc>
|
||||||
<lastmod>2018-06-12</lastmod>
|
<lastmod>2018-06-20</lastmod>
|
||||||
<changefreq>daily</changefreq>
|
<changefreq>daily</changefreq>
|
||||||
</url>
|
</url>
|
||||||
|
|
||||||
@@ -52,7 +52,7 @@
|
|||||||
|
|
||||||
<url>
|
<url>
|
||||||
<loc>/merge/</loc>
|
<loc>/merge/</loc>
|
||||||
<lastmod>2018-06-12</lastmod>
|
<lastmod>2018-06-20</lastmod>
|
||||||
<changefreq>daily</changefreq>
|
<changefreq>daily</changefreq>
|
||||||
</url>
|
</url>
|
||||||
|
|
||||||
|
|||||||
@@ -275,6 +275,20 @@
|
|||||||
Appending value to an array field
|
Appending value to an array field
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li class="md-nav__item">
|
||||||
|
<a href="#multiple-documents-update-a-single-document" title="Multiple Documents - update a single document" class="md-nav__link">
|
||||||
|
Multiple Documents - update a single document
|
||||||
|
</a>
|
||||||
|
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li class="md-nav__item">
|
||||||
|
<a href="#multiple-documents-update-all-documents" title="Multiple Documents - update all documents" class="md-nav__link">
|
||||||
|
Multiple Documents - update all documents
|
||||||
|
</a>
|
||||||
|
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
<li class="md-nav__item">
|
<li class="md-nav__item">
|
||||||
@@ -406,6 +420,20 @@
|
|||||||
Appending value to an array field
|
Appending value to an array field
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li class="md-nav__item">
|
||||||
|
<a href="#multiple-documents-update-a-single-document" title="Multiple Documents - update a single document" class="md-nav__link">
|
||||||
|
Multiple Documents - update a single document
|
||||||
|
</a>
|
||||||
|
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li class="md-nav__item">
|
||||||
|
<a href="#multiple-documents-update-all-documents" title="Multiple Documents - update all documents" class="md-nav__link">
|
||||||
|
Multiple Documents - update all documents
|
||||||
|
</a>
|
||||||
|
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
<li class="md-nav__item">
|
<li class="md-nav__item">
|
||||||
@@ -455,10 +483,9 @@
|
|||||||
|
|
||||||
<h1>Write/Update</h1>
|
<h1>Write/Update</h1>
|
||||||
|
|
||||||
<pre><code>yq w <yaml_file|json_file> <path> <new value>
|
<pre><code>yq w <yaml_file> <path> <new value>
|
||||||
</code></pre>
|
</code></pre>
|
||||||
|
|
||||||
<p>This command can take a json file as input too, and will output yaml unless specified to export as json (-j)</p>
|
|
||||||
<h3 id="to-stdout">To Stdout<a class="headerlink" href="#to-stdout" title="Permanent link">¶</a></h3>
|
<h3 id="to-stdout">To Stdout<a class="headerlink" href="#to-stdout" title="Permanent link">¶</a></h3>
|
||||||
<p>Given a sample.yaml file of:</p>
|
<p>Given a sample.yaml file of:</p>
|
||||||
<pre><code class="yaml">b:
|
<pre><code class="yaml">b:
|
||||||
@@ -519,6 +546,47 @@
|
|||||||
</code></pre>
|
</code></pre>
|
||||||
|
|
||||||
<p>Note that the path is in quotes to avoid the square brackets being interpreted by your shell.</p>
|
<p>Note that the path is in quotes to avoid the square brackets being interpreted by your shell.</p>
|
||||||
|
<h3 id="multiple-documents-update-a-single-document">Multiple Documents - update a single document<a class="headerlink" href="#multiple-documents-update-a-single-document" title="Permanent link">¶</a></h3>
|
||||||
|
<p>Given a sample.yaml file of:</p>
|
||||||
|
<pre><code class="yaml">something: else
|
||||||
|
---
|
||||||
|
b:
|
||||||
|
c: 2
|
||||||
|
</code></pre>
|
||||||
|
|
||||||
|
<p>then</p>
|
||||||
|
<pre><code class="bash">yq w -d1 sample.yaml b.c 5
|
||||||
|
</code></pre>
|
||||||
|
|
||||||
|
<p>will output:</p>
|
||||||
|
<pre><code class="yaml">something: else
|
||||||
|
---
|
||||||
|
b:
|
||||||
|
c: 5
|
||||||
|
</code></pre>
|
||||||
|
|
||||||
|
<h3 id="multiple-documents-update-all-documents">Multiple Documents - update all documents<a class="headerlink" href="#multiple-documents-update-all-documents" title="Permanent link">¶</a></h3>
|
||||||
|
<p>Given a sample.yaml file of:</p>
|
||||||
|
<pre><code class="yaml">something: else
|
||||||
|
---
|
||||||
|
b:
|
||||||
|
c: 2
|
||||||
|
</code></pre>
|
||||||
|
|
||||||
|
<p>then</p>
|
||||||
|
<pre><code class="bash">yq w -d'*' sample.yaml b.c 5
|
||||||
|
</code></pre>
|
||||||
|
|
||||||
|
<p>will output:</p>
|
||||||
|
<pre><code class="yaml">something: else
|
||||||
|
b:
|
||||||
|
c: 5
|
||||||
|
---
|
||||||
|
b:
|
||||||
|
c: 5
|
||||||
|
</code></pre>
|
||||||
|
|
||||||
|
<p>Note that '*' is in quotes to avoid being interpreted by your shell.</p>
|
||||||
<h3 id="updating-files-in-place">Updating files in-place<a class="headerlink" href="#updating-files-in-place" title="Permanent link">¶</a></h3>
|
<h3 id="updating-files-in-place">Updating files in-place<a class="headerlink" href="#updating-files-in-place" title="Permanent link">¶</a></h3>
|
||||||
<p>Given a sample.yaml file of:</p>
|
<p>Given a sample.yaml file of:</p>
|
||||||
<pre><code class="yaml">b:
|
<pre><code class="yaml">b:
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
a: other
|
a: other
|
||||||
|
b: [3, 4]
|
||||||
c:
|
c:
|
||||||
test: 1
|
test: 1
|
||||||
|
|||||||
@@ -1,5 +1 @@
|
|||||||
b: [2, 3, 4]
|
b: dog
|
||||||
c:
|
|
||||||
test: 2
|
|
||||||
other: true
|
|
||||||
d: false
|
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
|
commonKey: first document
|
||||||
a: Easy! as one two three
|
a: Easy! as one two three
|
||||||
b:
|
b:
|
||||||
c: 2
|
c: 2
|
||||||
@@ -8,8 +9,10 @@ b:
|
|||||||
- name: sam
|
- name: sam
|
||||||
value: 4
|
value: 4
|
||||||
---
|
---
|
||||||
|
commonKey: second document
|
||||||
another:
|
another:
|
||||||
document: here
|
document: here
|
||||||
---
|
---
|
||||||
|
commonKey: third document
|
||||||
wow:
|
wow:
|
||||||
- here is another
|
- here is another
|
||||||
1
examples/sample_array_2.yaml
Normal file
1
examples/sample_array_2.yaml
Normal file
@@ -0,0 +1 @@
|
|||||||
|
[4,5]
|
||||||
@@ -5,7 +5,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
yaml "gopkg.in/yaml.v2"
|
yaml "gopkg.in/mikefarah/yaml.v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
func jsonToString(context interface{}) (string, error) {
|
func jsonToString(context interface{}) (string, error) {
|
||||||
|
|||||||
10
merge.go
10
merge.go
@@ -1,12 +1,12 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import "gopkg.in/imdario/mergo.v0"
|
||||||
"github.com/imdario/mergo"
|
|
||||||
)
|
|
||||||
|
|
||||||
func merge(dst, src interface{}, overwrite bool) error {
|
func merge(dst interface{}, src interface{}, overwrite bool, append bool) error {
|
||||||
if overwrite {
|
if overwrite {
|
||||||
return mergo.MergeWithOverwrite(dst, src)
|
return mergo.Merge(dst, src, mergo.WithOverride)
|
||||||
|
} else if append {
|
||||||
|
return mergo.Merge(dst, src, mergo.WithAppendSlice)
|
||||||
}
|
}
|
||||||
return mergo.Merge(dst, src)
|
return mergo.Merge(dst, src)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
### Yaml to Json
|
### Yaml to Json
|
||||||
To convert output to json, use the --tojson (or -j) flag. This can be used with any command.
|
To convert output to json, use the --tojson (or -j) flag. This can only be used with the read command.
|
||||||
|
|
||||||
Given a sample.yaml file of:
|
Given a sample.yaml file of:
|
||||||
```yaml
|
```yaml
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
Yaml files can be created using the 'new' command. This works in the same way as the write command, but you don't pass in an existing Yaml file.
|
Yaml files can be created using the 'new' command. This works in the same way as the write command, but you don't pass in an existing Yaml file. Currently this does not support creating multiple documents in a single yaml file.
|
||||||
|
|
||||||
```
|
```
|
||||||
yq n <path> <new value>
|
yq n <path> <new value>
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
```
|
```
|
||||||
yq d <yaml_file|json_file> <path_to_delete>
|
yq d <yaml_file> <path_to_delete>
|
||||||
```
|
```
|
||||||
{!snippets/works_with_json.md!}
|
|
||||||
|
|
||||||
### To Stdout
|
### To Stdout
|
||||||
Given a sample.yaml file of:
|
Given a sample.yaml file of:
|
||||||
@@ -60,4 +59,52 @@ yq d -i sample.yaml b.c
|
|||||||
will update the sample.yaml file so that the 'c' node is deleted
|
will update the sample.yaml file so that the 'c' node is deleted
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### Multiple Documents - delete from single document
|
||||||
|
Given a sample.yaml file of:
|
||||||
|
```yaml
|
||||||
|
something: else
|
||||||
|
field: leaveMe
|
||||||
|
---
|
||||||
|
b:
|
||||||
|
c: 2
|
||||||
|
field: deleteMe
|
||||||
|
```
|
||||||
|
then
|
||||||
|
```bash
|
||||||
|
yq w -d1 sample.yaml field
|
||||||
|
```
|
||||||
|
will output:
|
||||||
|
```yaml
|
||||||
|
something: else
|
||||||
|
field: leaveMe
|
||||||
|
---
|
||||||
|
b:
|
||||||
|
c: 2
|
||||||
|
```
|
||||||
|
|
||||||
|
### Multiple Documents - delete from all documents
|
||||||
|
Given a sample.yaml file of:
|
||||||
|
```yaml
|
||||||
|
something: else
|
||||||
|
field: deleteMe
|
||||||
|
---
|
||||||
|
b:
|
||||||
|
c: 2
|
||||||
|
field: deleteMeToo
|
||||||
|
```
|
||||||
|
then
|
||||||
|
```bash
|
||||||
|
yq w -d'*' sample.yaml field
|
||||||
|
```
|
||||||
|
will output:
|
||||||
|
```yaml
|
||||||
|
something: else
|
||||||
|
---
|
||||||
|
b:
|
||||||
|
c: 2
|
||||||
|
```
|
||||||
|
|
||||||
|
Note that '*' is in quotes to avoid being interpreted by your shell.
|
||||||
|
|
||||||
{!snippets/keys_with_dots.md!}
|
{!snippets/keys_with_dots.md!}
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ sudo apt install yq -y
|
|||||||
```
|
```
|
||||||
or, [Download latest binary](https://github.com/mikefarah/yq/releases/latest) or alternatively:
|
or, [Download latest binary](https://github.com/mikefarah/yq/releases/latest) or alternatively:
|
||||||
```
|
```
|
||||||
go get github.com/mikefarah/yq
|
go get gopkg.in/mikefarah/yq.v2
|
||||||
```
|
```
|
||||||
|
|
||||||
[View on GitHub](https://github.com/mikefarah/yq)
|
[View on GitHub](https://github.com/mikefarah/yq)
|
||||||
|
|||||||
@@ -2,9 +2,9 @@ Yaml files can be merged using the 'merge' command. Each additional file merged
|
|||||||
set values for any key not existing already or where the key has no value.
|
set values for any key not existing already or where the key has no value.
|
||||||
|
|
||||||
```
|
```
|
||||||
yq m <yaml_file|json_file> <path>...
|
yq m <yaml_file> <path>...
|
||||||
```
|
```
|
||||||
{!snippets/works_with_json.md!}
|
|
||||||
|
|
||||||
### To Stdout
|
### To Stdout
|
||||||
Given a data1.yaml file of:
|
Given a data1.yaml file of:
|
||||||
@@ -102,3 +102,56 @@ d: false
|
|||||||
|
|
||||||
Notice that 'b' does not result in the merging of the values within an array. The underlying library does not
|
Notice that 'b' does not result in the merging of the values within an array. The underlying library does not
|
||||||
currently handle merging values within an array.
|
currently handle merging values within an array.
|
||||||
|
|
||||||
|
### Multiple Documents - merge into single document
|
||||||
|
Currently yq only has multi-document support for the _first_ document being merged into. The remaining yaml files will have their first document selected.
|
||||||
|
|
||||||
|
Given a data1.yaml file of:
|
||||||
|
```yaml
|
||||||
|
something: else
|
||||||
|
---
|
||||||
|
a: simple
|
||||||
|
b: cat
|
||||||
|
```
|
||||||
|
and data3.yaml file of:
|
||||||
|
```yaml
|
||||||
|
b: dog
|
||||||
|
```
|
||||||
|
then
|
||||||
|
```bash
|
||||||
|
yq m -x -d1 data1.yaml data3.yaml
|
||||||
|
```
|
||||||
|
will output:
|
||||||
|
```yaml
|
||||||
|
something: else
|
||||||
|
---
|
||||||
|
a: simple
|
||||||
|
b: dog
|
||||||
|
```
|
||||||
|
|
||||||
|
### Multiple Documents - merge into all documents
|
||||||
|
Currently yq only has multi-document support for the _first_ document being merged into. The remaining yaml files will have their first document selected.
|
||||||
|
|
||||||
|
Given a data1.yaml file of:
|
||||||
|
```yaml
|
||||||
|
something: else
|
||||||
|
---
|
||||||
|
a: simple
|
||||||
|
b: cat
|
||||||
|
```
|
||||||
|
and data3.yaml file of:
|
||||||
|
```yaml
|
||||||
|
b: dog
|
||||||
|
```
|
||||||
|
then
|
||||||
|
```bash
|
||||||
|
yq m -x -d'*' data1.yaml data3.yaml
|
||||||
|
```
|
||||||
|
will output:
|
||||||
|
```yaml
|
||||||
|
b: dog
|
||||||
|
something: else
|
||||||
|
---
|
||||||
|
a: simple
|
||||||
|
b: dog
|
||||||
|
```
|
||||||
@@ -43,6 +43,20 @@ will output
|
|||||||
- apples
|
- apples
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Multiple Documents
|
||||||
|
Given a sample.yaml file of:
|
||||||
|
```yaml
|
||||||
|
something: else
|
||||||
|
---
|
||||||
|
b:
|
||||||
|
c: 2
|
||||||
|
```
|
||||||
|
then
|
||||||
|
```bash
|
||||||
|
yq r -d1 sample.yaml b.c
|
||||||
|
```
|
||||||
|
will output the value of '2'.
|
||||||
|
|
||||||
### Arrays
|
### Arrays
|
||||||
You can give an index to access a specific element:
|
You can give an index to access a specific element:
|
||||||
e.g.: given a sample file of
|
e.g.: given a sample file of
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
```
|
```
|
||||||
yq w <yaml_file|json_file> <path> <new value>
|
yq w <yaml_file> <path> <new value>
|
||||||
```
|
```
|
||||||
{!snippets/works_with_json.md!}
|
|
||||||
|
|
||||||
### To Stdout
|
### To Stdout
|
||||||
Given a sample.yaml file of:
|
Given a sample.yaml file of:
|
||||||
@@ -69,6 +68,50 @@ b:
|
|||||||
|
|
||||||
Note that the path is in quotes to avoid the square brackets being interpreted by your shell.
|
Note that the path is in quotes to avoid the square brackets being interpreted by your shell.
|
||||||
|
|
||||||
|
### Multiple Documents - update a single document
|
||||||
|
Given a sample.yaml file of:
|
||||||
|
```yaml
|
||||||
|
something: else
|
||||||
|
---
|
||||||
|
b:
|
||||||
|
c: 2
|
||||||
|
```
|
||||||
|
then
|
||||||
|
```bash
|
||||||
|
yq w -d1 sample.yaml b.c 5
|
||||||
|
```
|
||||||
|
will output:
|
||||||
|
```yaml
|
||||||
|
something: else
|
||||||
|
---
|
||||||
|
b:
|
||||||
|
c: 5
|
||||||
|
```
|
||||||
|
|
||||||
|
### Multiple Documents - update all documents
|
||||||
|
Given a sample.yaml file of:
|
||||||
|
```yaml
|
||||||
|
something: else
|
||||||
|
---
|
||||||
|
b:
|
||||||
|
c: 2
|
||||||
|
```
|
||||||
|
then
|
||||||
|
```bash
|
||||||
|
yq w -d'*' sample.yaml b.c 5
|
||||||
|
```
|
||||||
|
will output:
|
||||||
|
```yaml
|
||||||
|
something: else
|
||||||
|
b:
|
||||||
|
c: 5
|
||||||
|
---
|
||||||
|
b:
|
||||||
|
c: 5
|
||||||
|
```
|
||||||
|
|
||||||
|
Note that '*' is in quotes to avoid being interpreted by your shell.
|
||||||
|
|
||||||
### Updating files in-place
|
### Updating files in-place
|
||||||
Given a sample.yaml file of:
|
Given a sample.yaml file of:
|
||||||
```yaml
|
```yaml
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
- increment version in version.go
|
- increment version in version.go
|
||||||
- increment version in snapcraft.yaml
|
- increment version in snapcraft.yaml
|
||||||
- tag git with same version number
|
- tag git with same version number, be sure to start with 'v' for gopkg.in
|
||||||
- make sure local build passes
|
- make sure local build passes
|
||||||
- push tag to git
|
- push tag to git
|
||||||
- make local xcompile (builds binaries for all platforms)
|
- make local xcompile (builds binaries for all platforms)
|
||||||
@@ -10,6 +10,13 @@
|
|||||||
|
|
||||||
- snapcraft
|
- snapcraft
|
||||||
- will auto create a candidate, test it works then promote
|
- will auto create a candidate, test it works then promote
|
||||||
|
- see https://build.snapcraft.io/user/mikefarah/yq
|
||||||
|
|
||||||
|
sudo snap remove yq
|
||||||
|
sudo snap install --edge yq
|
||||||
|
|
||||||
|
then on the mac snapcraft release yq <snap_build_number> stable
|
||||||
|
|
||||||
|
|
||||||
- brew
|
- brew
|
||||||
- create pull request pointing to latest git release
|
- create pull request pointing to latest git release
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
name: yq
|
name: yq
|
||||||
version: 1.15.0
|
version: 2.0.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.
|
||||||
|
|||||||
@@ -9,8 +9,8 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/spf13/cobra"
|
yaml "gopkg.in/mikefarah/yaml.v2"
|
||||||
yaml "gopkg.in/yaml.v2"
|
"gopkg.in/spf13/cobra.v0"
|
||||||
)
|
)
|
||||||
|
|
||||||
type resulter struct {
|
type resulter struct {
|
||||||
|
|||||||
50
vendor/vendor.json
vendored
50
vendor/vendor.json
vendored
@@ -2,24 +2,12 @@
|
|||||||
"comment": "",
|
"comment": "",
|
||||||
"ignore": "test",
|
"ignore": "test",
|
||||||
"package": [
|
"package": [
|
||||||
{
|
|
||||||
"checksumSHA1": "66lykxpWgSmQodnhkADqn6tnroQ=",
|
|
||||||
"path": "github.com/imdario/mergo",
|
|
||||||
"revision": "e3000cb3d28c72b837601cac94debd91032d19fe",
|
|
||||||
"revisionTime": "2017-06-20T10:47:01Z"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"checksumSHA1": "40vJyUB4ezQSn/NSadsKEOrudMc=",
|
"checksumSHA1": "40vJyUB4ezQSn/NSadsKEOrudMc=",
|
||||||
"path": "github.com/inconshreveable/mousetrap",
|
"path": "github.com/inconshreveable/mousetrap",
|
||||||
"revision": "76626ae9c91c4f2a10f34cad8ce83ea42c93bb75",
|
"revision": "76626ae9c91c4f2a10f34cad8ce83ea42c93bb75",
|
||||||
"revisionTime": "2014-10-17T20:07:13Z"
|
"revisionTime": "2014-10-17T20:07:13Z"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"checksumSHA1": "BoXdUBWB8UnSlFlbnuTQaPqfCGk=",
|
|
||||||
"path": "github.com/op/go-logging",
|
|
||||||
"revision": "970db520ece77730c7e4724c61121037378659d9",
|
|
||||||
"revisionTime": "2016-03-15T20:05:05Z"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"checksumSHA1": "ljd3FhYRJ91cLZz3wsH9BQQ2JbA=",
|
"checksumSHA1": "ljd3FhYRJ91cLZz3wsH9BQQ2JbA=",
|
||||||
"path": "github.com/pkg/errors",
|
"path": "github.com/pkg/errors",
|
||||||
@@ -27,24 +15,34 @@
|
|||||||
"revisionTime": "2018-03-11T21:45:15Z"
|
"revisionTime": "2018-03-11T21:45:15Z"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"checksumSHA1": "xPKgXygsORkmXnLdtFaFmipYKaA=",
|
"checksumSHA1": "OJI0OgC5V8gZtfS1e0CDYMhkDNc=",
|
||||||
"path": "github.com/spf13/cobra",
|
|
||||||
"revision": "b78744579491c1ceeaaa3b40205e56b0591b93a3",
|
|
||||||
"revisionTime": "2017-09-05T17:20:51Z"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"checksumSHA1": "Q52Y7t0lEtk/wcDn5q7tS7B+jqs=",
|
|
||||||
"path": "github.com/spf13/pflag",
|
"path": "github.com/spf13/pflag",
|
||||||
"revision": "7aff26db30c1be810f9de5038ec5ef96ac41fd7c",
|
"revision": "3ebe029320b2676d667ae88da602a5f854788a8a",
|
||||||
"revisionTime": "2017-08-24T17:57:12Z"
|
"revisionTime": "2018-06-01T13:25:42Z"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"checksumSHA1": "DHNYKS5T54/XOqUsFFzdZMLEnVE=",
|
"checksumSHA1": "RwlkCZz8VFXAE4aHQQOSC0hLu5k=",
|
||||||
"origin": "github.com/mikefarah/yaml",
|
"path": "gopkg.in/imdario/mergo.v0",
|
||||||
"path": "gopkg.in/yaml.v2",
|
"revision": "9316a62528ac99aaecb4e47eadd6dc8aa6533d58",
|
||||||
|
"revisionTime": "2018-06-08T14:01:56Z"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"checksumSHA1": "7wtGubs4v7+RZovtlmyT9KwA/gE=",
|
||||||
|
"path": "gopkg.in/mikefarah/yaml.v2",
|
||||||
"revision": "e175af14aaa1d0eff2ee04b691e4a4827a111416",
|
"revision": "e175af14aaa1d0eff2ee04b691e4a4827a111416",
|
||||||
"revisionTime": "2018-06-13T04:05:11Z",
|
"revisionTime": "2018-06-13T04:05:11Z"
|
||||||
"tree": true
|
},
|
||||||
|
{
|
||||||
|
"checksumSHA1": "rL5r44ASTGubGW88gqQwlvVQshw=",
|
||||||
|
"path": "gopkg.in/op/go-logging.v1",
|
||||||
|
"revision": "b2cb9fa56473e98db8caba80237377e83fe44db5",
|
||||||
|
"revisionTime": "2016-02-11T21:21:56Z"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"checksumSHA1": "xsZjAbfLrXcMtY6fyQ8QC6EvJD0=",
|
||||||
|
"path": "gopkg.in/spf13/cobra.v0",
|
||||||
|
"revision": "ef82de70bb3f60c65fb8eebacbb2d122ef517385",
|
||||||
|
"revisionTime": "2018-04-27T13:45:50Z"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"rootPath": "github.com/mikefarah/yq"
|
"rootPath": "github.com/mikefarah/yq"
|
||||||
|
|||||||
@@ -11,12 +11,12 @@ 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 = "2.0.0"
|
Version = "2.1.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
|
||||||
// such as "dev" (in development), "beta", "rc1", etc.
|
// such as "dev" (in development), "beta", "rc1", etc.
|
||||||
VersionPrerelease = "beta"
|
VersionPrerelease = ""
|
||||||
)
|
)
|
||||||
|
|
||||||
// ProductName is the name of the product
|
// ProductName is the name of the product
|
||||||
|
|||||||
@@ -3,13 +3,18 @@ package main
|
|||||||
import "testing"
|
import "testing"
|
||||||
|
|
||||||
func TestGetVersionDisplay(t *testing.T) {
|
func TestGetVersionDisplay(t *testing.T) {
|
||||||
|
var expectedVersion = ProductName + " version " + Version
|
||||||
|
if VersionPrerelease != "" {
|
||||||
|
expectedVersion = expectedVersion + "-" + VersionPrerelease
|
||||||
|
}
|
||||||
|
expectedVersion = expectedVersion + "\n"
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
want string
|
want string
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "Display Version",
|
name: "Display Version",
|
||||||
want: ProductName + " version " + Version + "-" + VersionPrerelease + "\n",
|
want: expectedVersion,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
|
|||||||
190
yq.go
190
yq.go
@@ -11,10 +11,10 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
errors "github.com/pkg/errors"
|
errors "github.com/pkg/errors"
|
||||||
|
"gopkg.in/spf13/cobra.v0"
|
||||||
|
|
||||||
logging "github.com/op/go-logging"
|
yaml "gopkg.in/mikefarah/yaml.v2"
|
||||||
"github.com/spf13/cobra"
|
logging "gopkg.in/op/go-logging.v1"
|
||||||
yaml "gopkg.in/yaml.v2"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var trimOutput = true
|
var trimOutput = true
|
||||||
@@ -22,9 +22,10 @@ var writeInplace = false
|
|||||||
var writeScript = ""
|
var writeScript = ""
|
||||||
var outputToJSON = false
|
var outputToJSON = false
|
||||||
var overwriteFlag = false
|
var overwriteFlag = false
|
||||||
|
var appendFlag = false
|
||||||
var verbose = false
|
var verbose = false
|
||||||
var version = false
|
var version = false
|
||||||
var docIndex = 0
|
var docIndex = "0"
|
||||||
var log = logging.MustGetLogger("yq")
|
var log = logging.MustGetLogger("yq")
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
@@ -66,7 +67,6 @@ func newCommandCLI() *cobra.Command {
|
|||||||
}
|
}
|
||||||
|
|
||||||
rootCmd.PersistentFlags().BoolVarP(&trimOutput, "trim", "t", true, "trim yaml output")
|
rootCmd.PersistentFlags().BoolVarP(&trimOutput, "trim", "t", true, "trim yaml output")
|
||||||
rootCmd.PersistentFlags().BoolVarP(&outputToJSON, "tojson", "j", false, "output as json")
|
|
||||||
rootCmd.PersistentFlags().BoolVarP(&verbose, "verbose", "v", false, "verbose mode")
|
rootCmd.PersistentFlags().BoolVarP(&verbose, "verbose", "v", false, "verbose mode")
|
||||||
rootCmd.Flags().BoolVarP(&version, "version", "V", false, "Print version information and quit")
|
rootCmd.Flags().BoolVarP(&version, "version", "V", false, "Print version information and quit")
|
||||||
|
|
||||||
@@ -86,7 +86,7 @@ func createReadCmd() *cobra.Command {
|
|||||||
var cmdRead = &cobra.Command{
|
var cmdRead = &cobra.Command{
|
||||||
Use: "read [yaml_file] [path]",
|
Use: "read [yaml_file] [path]",
|
||||||
Aliases: []string{"r"},
|
Aliases: []string{"r"},
|
||||||
Short: "yq r [--doc/-d document_index] sample.yaml a.b.c",
|
Short: "yq r [--doc/-d index] sample.yaml a.b.c",
|
||||||
Example: `
|
Example: `
|
||||||
yq read things.yaml a.b.c
|
yq read things.yaml a.b.c
|
||||||
yq r - a.b.c (reads from stdin)
|
yq r - a.b.c (reads from stdin)
|
||||||
@@ -97,7 +97,8 @@ yq r things.yaml a.array[*].blah
|
|||||||
Long: "Outputs the value of the given path in the yaml file to STDOUT",
|
Long: "Outputs the value of the given path in the yaml file to STDOUT",
|
||||||
RunE: readProperty,
|
RunE: readProperty,
|
||||||
}
|
}
|
||||||
cmdRead.PersistentFlags().IntVarP(&docIndex, "doc", "d", 0, "process document index number (0 based)")
|
cmdRead.PersistentFlags().StringVarP(&docIndex, "doc", "d", "0", "process document index number (0 based, * for all documents)")
|
||||||
|
cmdRead.PersistentFlags().BoolVarP(&outputToJSON, "tojson", "j", false, "output as json")
|
||||||
return cmdRead
|
return cmdRead
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -105,7 +106,7 @@ func createWriteCmd() *cobra.Command {
|
|||||||
var cmdWrite = &cobra.Command{
|
var cmdWrite = &cobra.Command{
|
||||||
Use: "write [yaml_file] [path] [value]",
|
Use: "write [yaml_file] [path] [value]",
|
||||||
Aliases: []string{"w"},
|
Aliases: []string{"w"},
|
||||||
Short: "yq w [--inplace/-i] [--script/-s script_file] [--doc/-d document_index] sample.yaml a.b.c newValueForC",
|
Short: "yq w [--inplace/-i] [--script/-s script_file] [--doc/-d index] sample.yaml a.b.c newValue",
|
||||||
Example: `
|
Example: `
|
||||||
yq write things.yaml a.b.c cat
|
yq write things.yaml a.b.c cat
|
||||||
yq write --inplace things.yaml a.b.c cat
|
yq write --inplace things.yaml a.b.c cat
|
||||||
@@ -132,7 +133,7 @@ a.b.e:
|
|||||||
}
|
}
|
||||||
cmdWrite.PersistentFlags().BoolVarP(&writeInplace, "inplace", "i", false, "update the yaml file inplace")
|
cmdWrite.PersistentFlags().BoolVarP(&writeInplace, "inplace", "i", false, "update the yaml file inplace")
|
||||||
cmdWrite.PersistentFlags().StringVarP(&writeScript, "script", "s", "", "yaml script for updating yaml")
|
cmdWrite.PersistentFlags().StringVarP(&writeScript, "script", "s", "", "yaml script for updating yaml")
|
||||||
cmdWrite.PersistentFlags().IntVarP(&docIndex, "doc", "d", 0, "process document index number (0 based)")
|
cmdWrite.PersistentFlags().StringVarP(&docIndex, "doc", "d", "0", "process document index number (0 based, * for all documents)")
|
||||||
return cmdWrite
|
return cmdWrite
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -140,7 +141,7 @@ func createDeleteCmd() *cobra.Command {
|
|||||||
var cmdDelete = &cobra.Command{
|
var cmdDelete = &cobra.Command{
|
||||||
Use: "delete [yaml_file] [path]",
|
Use: "delete [yaml_file] [path]",
|
||||||
Aliases: []string{"d"},
|
Aliases: []string{"d"},
|
||||||
Short: "yq d [--inplace/-i] [--doc/-d document_index] sample.yaml a.b.c",
|
Short: "yq d [--inplace/-i] [--doc/-d index] sample.yaml a.b.c",
|
||||||
Example: `
|
Example: `
|
||||||
yq delete things.yaml a.b.c
|
yq delete things.yaml a.b.c
|
||||||
yq delete --inplace things.yaml a.b.c
|
yq delete --inplace things.yaml a.b.c
|
||||||
@@ -153,7 +154,7 @@ Outputs to STDOUT unless the inplace flag is used, in which case the file is upd
|
|||||||
RunE: deleteProperty,
|
RunE: deleteProperty,
|
||||||
}
|
}
|
||||||
cmdDelete.PersistentFlags().BoolVarP(&writeInplace, "inplace", "i", false, "update the yaml file inplace")
|
cmdDelete.PersistentFlags().BoolVarP(&writeInplace, "inplace", "i", false, "update the yaml file inplace")
|
||||||
cmdDelete.PersistentFlags().IntVarP(&docIndex, "doc", "d", 0, "process document index number (0 based)")
|
cmdDelete.PersistentFlags().StringVarP(&docIndex, "doc", "d", "0", "process document index number (0 based, * for all documents)")
|
||||||
return cmdDelete
|
return cmdDelete
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -161,7 +162,7 @@ func createNewCmd() *cobra.Command {
|
|||||||
var cmdNew = &cobra.Command{
|
var cmdNew = &cobra.Command{
|
||||||
Use: "new [path] [value]",
|
Use: "new [path] [value]",
|
||||||
Aliases: []string{"n"},
|
Aliases: []string{"n"},
|
||||||
Short: "yq n [--script/-s script_file] a.b.c newValueForC",
|
Short: "yq n [--script/-s script_file] a.b.c newValue",
|
||||||
Example: `
|
Example: `
|
||||||
yq new a.b.c cat
|
yq new a.b.c cat
|
||||||
yq n a.b.c cat
|
yq n a.b.c cat
|
||||||
@@ -183,33 +184,83 @@ func createMergeCmd() *cobra.Command {
|
|||||||
var cmdMerge = &cobra.Command{
|
var cmdMerge = &cobra.Command{
|
||||||
Use: "merge [initial_yaml_file] [additional_yaml_file]...",
|
Use: "merge [initial_yaml_file] [additional_yaml_file]...",
|
||||||
Aliases: []string{"m"},
|
Aliases: []string{"m"},
|
||||||
Short: "yq m [--inplace/-i] [--doc/-d document_index] [--overwrite/-x] sample.yaml sample2.yaml",
|
Short: "yq m [--inplace/-i] [--doc/-d index] [--overwrite/-x] [--append/-a] sample.yaml sample2.yaml",
|
||||||
Example: `
|
Example: `
|
||||||
yq merge things.yaml other.yaml
|
yq merge things.yaml other.yaml
|
||||||
yq merge --inplace things.yaml other.yaml
|
yq merge --inplace things.yaml other.yaml
|
||||||
yq m -i things.yaml other.yaml
|
yq m -i things.yaml other.yaml
|
||||||
yq m --overwrite things.yaml other.yaml
|
yq m --overwrite things.yaml other.yaml
|
||||||
yq m -i -x things.yaml other.yaml
|
yq m -i -x things.yaml other.yaml
|
||||||
|
yq m -i -a things.yaml other.yaml
|
||||||
`,
|
`,
|
||||||
Long: `Updates the yaml file by adding/updating the path(s) and value(s) from additional yaml file(s).
|
Long: `Updates the yaml file by adding/updating the path(s) and value(s) from additional yaml file(s).
|
||||||
Outputs to STDOUT unless the inplace flag is used, in which case the file is updated instead.
|
Outputs to STDOUT unless the inplace flag is used, in which case the file is updated instead.
|
||||||
|
|
||||||
If overwrite flag is set then existing values will be overwritten using the values from each additional yaml file.
|
If overwrite flag is set then existing values will be overwritten using the values from each additional yaml file.
|
||||||
|
If append flag is set then existing arrays will be merged with the arrays from each additional yaml file.
|
||||||
|
|
||||||
|
Note that if you set both flags only overwrite will take effect.
|
||||||
`,
|
`,
|
||||||
RunE: mergeProperties,
|
RunE: mergeProperties,
|
||||||
}
|
}
|
||||||
cmdMerge.PersistentFlags().BoolVarP(&writeInplace, "inplace", "i", false, "update the yaml file inplace")
|
cmdMerge.PersistentFlags().BoolVarP(&writeInplace, "inplace", "i", false, "update the yaml file inplace")
|
||||||
cmdMerge.PersistentFlags().BoolVarP(&overwriteFlag, "overwrite", "x", false, "update the yaml file by overwriting existing values")
|
cmdMerge.PersistentFlags().BoolVarP(&overwriteFlag, "overwrite", "x", false, "update the yaml file by overwriting existing values")
|
||||||
cmdMerge.PersistentFlags().IntVarP(&docIndex, "doc", "d", 0, "process document index number (0 based)")
|
cmdMerge.PersistentFlags().BoolVarP(&appendFlag, "append", "a", false, "update the yaml file by appending array values")
|
||||||
|
cmdMerge.PersistentFlags().StringVarP(&docIndex, "doc", "d", "0", "process document index number (0 based, * for all documents)")
|
||||||
return cmdMerge
|
return cmdMerge
|
||||||
}
|
}
|
||||||
|
|
||||||
func readProperty(cmd *cobra.Command, args []string) error {
|
func readProperty(cmd *cobra.Command, args []string) error {
|
||||||
data, err := read(args)
|
var path = ""
|
||||||
if err != nil {
|
|
||||||
return err
|
if len(args) < 1 {
|
||||||
|
return errors.New("Must provide filename")
|
||||||
|
} else if len(args) > 1 {
|
||||||
|
path = args[1]
|
||||||
}
|
}
|
||||||
dataStr, err := toString(data)
|
|
||||||
|
var updateAll, docIndexInt, errorParsingDocIndex = parseDocumentIndex()
|
||||||
|
if errorParsingDocIndex != nil {
|
||||||
|
return errorParsingDocIndex
|
||||||
|
}
|
||||||
|
var mappedDocs []interface{}
|
||||||
|
var dataBucket interface{}
|
||||||
|
var currentIndex = 0
|
||||||
|
var errorReadingStream = readStream(args[0], func(decoder *yaml.Decoder) error {
|
||||||
|
for {
|
||||||
|
errorReading := decoder.Decode(&dataBucket)
|
||||||
|
if errorReading == io.EOF {
|
||||||
|
log.Debugf("done %v / %v", currentIndex, docIndexInt)
|
||||||
|
if !updateAll && currentIndex <= docIndexInt {
|
||||||
|
return fmt.Errorf("Asked to process document index %v but there are only %v document(s)", docIndex, currentIndex)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
log.Debugf("processing %v - requested index %v", currentIndex, docIndexInt)
|
||||||
|
if updateAll || currentIndex == docIndexInt {
|
||||||
|
log.Debugf("reading %v in index %v", path, currentIndex)
|
||||||
|
mappedDoc, errorParsing := readPath(dataBucket, path)
|
||||||
|
log.Debugf("%v", mappedDoc)
|
||||||
|
if errorParsing != nil {
|
||||||
|
return errors.Wrapf(errorParsing, "Error reading path in document index %v", currentIndex)
|
||||||
|
}
|
||||||
|
mappedDocs = append(mappedDocs, mappedDoc)
|
||||||
|
}
|
||||||
|
currentIndex = currentIndex + 1
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
if errorReadingStream != nil {
|
||||||
|
return errorReadingStream
|
||||||
|
}
|
||||||
|
|
||||||
|
if !updateAll {
|
||||||
|
dataBucket = mappedDocs[0]
|
||||||
|
} else {
|
||||||
|
dataBucket = mappedDocs
|
||||||
|
}
|
||||||
|
|
||||||
|
dataStr, err := toString(dataBucket)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -217,25 +268,13 @@ func readProperty(cmd *cobra.Command, args []string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func read(args []string) (interface{}, error) {
|
func readPath(dataBucket interface{}, path string) (interface{}, error) {
|
||||||
var path = ""
|
|
||||||
|
|
||||||
if len(args) < 1 {
|
|
||||||
return nil, errors.New("Must provide filename")
|
|
||||||
} else if len(args) > 1 {
|
|
||||||
path = args[1]
|
|
||||||
}
|
|
||||||
var generalData interface{}
|
|
||||||
if err := readData(args[0], docIndex, &generalData); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
if path == "" {
|
if path == "" {
|
||||||
return generalData, nil
|
log.Debug("no path")
|
||||||
|
return dataBucket, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
var paths = parsePath(path)
|
var paths = parsePath(path)
|
||||||
value, err := recurse(generalData, paths[0], paths[1:])
|
return recurse(dataBucket, paths[0], paths[1:])
|
||||||
return value, err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func newProperty(cmd *cobra.Command, args []string) error {
|
func newProperty(cmd *cobra.Command, args []string) error {
|
||||||
@@ -276,6 +315,17 @@ func newYaml(args []string) (interface{}, error) {
|
|||||||
return dataBucket, nil
|
return dataBucket, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func parseDocumentIndex() (bool, int, error) {
|
||||||
|
if docIndex == "*" {
|
||||||
|
return true, -1, nil
|
||||||
|
}
|
||||||
|
docIndexInt64, err := strconv.ParseInt(docIndex, 10, 32)
|
||||||
|
if err != nil {
|
||||||
|
return false, -1, errors.Wrapf(err, "Document index %v is not a integer or *", docIndex)
|
||||||
|
}
|
||||||
|
return false, int(docIndexInt64), nil
|
||||||
|
}
|
||||||
|
|
||||||
type updateDataFn func(dataBucket interface{}, currentIndex int) (interface{}, error)
|
type updateDataFn func(dataBucket interface{}, currentIndex int) (interface{}, error)
|
||||||
|
|
||||||
func mapYamlDecoder(updateData updateDataFn, encoder *yaml.Encoder) yamlDecoderFn {
|
func mapYamlDecoder(updateData updateDataFn, encoder *yaml.Encoder) yamlDecoderFn {
|
||||||
@@ -286,13 +336,18 @@ func mapYamlDecoder(updateData updateDataFn, encoder *yaml.Encoder) yamlDecoderF
|
|||||||
var errorUpdating error
|
var errorUpdating error
|
||||||
var currentIndex = 0
|
var currentIndex = 0
|
||||||
|
|
||||||
|
var updateAll, docIndexInt, errorParsingDocIndex = parseDocumentIndex()
|
||||||
|
if errorParsingDocIndex != nil {
|
||||||
|
return errorParsingDocIndex
|
||||||
|
}
|
||||||
|
|
||||||
for {
|
for {
|
||||||
log.Debugf("Read doc %v", currentIndex)
|
log.Debugf("Read doc %v", currentIndex)
|
||||||
errorReading = decoder.Decode(&dataBucket)
|
errorReading = decoder.Decode(&dataBucket)
|
||||||
|
|
||||||
if errorReading == io.EOF {
|
if errorReading == io.EOF {
|
||||||
if currentIndex < docIndex {
|
if !updateAll && currentIndex <= docIndexInt {
|
||||||
return fmt.Errorf("Asked to process document %v but there are only %v document(s)", docIndex, currentIndex)
|
return fmt.Errorf("Asked to process document index %v but there are only %v document(s)", docIndex, currentIndex)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
} else if errorReading != nil {
|
} else if errorReading != nil {
|
||||||
@@ -318,8 +373,13 @@ func writeProperty(cmd *cobra.Command, args []string) error {
|
|||||||
if writeCommandsError != nil {
|
if writeCommandsError != nil {
|
||||||
return writeCommandsError
|
return writeCommandsError
|
||||||
}
|
}
|
||||||
|
var updateAll, docIndexInt, errorParsingDocIndex = parseDocumentIndex()
|
||||||
|
if errorParsingDocIndex != nil {
|
||||||
|
return errorParsingDocIndex
|
||||||
|
}
|
||||||
|
|
||||||
var updateData = func(dataBucket interface{}, currentIndex int) (interface{}, error) {
|
var updateData = func(dataBucket interface{}, currentIndex int) (interface{}, error) {
|
||||||
if currentIndex == docIndex {
|
if updateAll || currentIndex == docIndexInt {
|
||||||
log.Debugf("Updating doc %v", currentIndex)
|
log.Debugf("Updating doc %v", currentIndex)
|
||||||
for _, entry := range writeCommands {
|
for _, entry := range writeCommands {
|
||||||
path := entry.Key.(string)
|
path := entry.Key.(string)
|
||||||
@@ -365,8 +425,13 @@ func deleteProperty(cmd *cobra.Command, args []string) error {
|
|||||||
}
|
}
|
||||||
var deletePath = args[1]
|
var deletePath = args[1]
|
||||||
var paths = parsePath(deletePath)
|
var paths = parsePath(deletePath)
|
||||||
|
var updateAll, docIndexInt, errorParsingDocIndex = parseDocumentIndex()
|
||||||
|
if errorParsingDocIndex != nil {
|
||||||
|
return errorParsingDocIndex
|
||||||
|
}
|
||||||
|
|
||||||
var updateData = func(dataBucket interface{}, currentIndex int) (interface{}, error) {
|
var updateData = func(dataBucket interface{}, currentIndex int) (interface{}, error) {
|
||||||
if currentIndex == docIndex {
|
if updateAll || currentIndex == docIndexInt {
|
||||||
log.Debugf("Deleting path in doc %v", currentIndex)
|
log.Debugf("Deleting path in doc %v", currentIndex)
|
||||||
return deleteChildValue(dataBucket, paths), nil
|
return deleteChildValue(dataBucket, paths), nil
|
||||||
}
|
}
|
||||||
@@ -382,12 +447,20 @@ func mergeProperties(cmd *cobra.Command, args []string) error {
|
|||||||
}
|
}
|
||||||
var input = args[0]
|
var input = args[0]
|
||||||
var filesToMerge = args[1:]
|
var filesToMerge = args[1:]
|
||||||
|
var updateAll, docIndexInt, errorParsingDocIndex = parseDocumentIndex()
|
||||||
|
if errorParsingDocIndex != nil {
|
||||||
|
return errorParsingDocIndex
|
||||||
|
}
|
||||||
|
|
||||||
var updateData = func(dataBucket interface{}, currentIndex int) (interface{}, error) {
|
var updateData = func(dataBucket interface{}, currentIndex int) (interface{}, error) {
|
||||||
if currentIndex == docIndex {
|
if updateAll || currentIndex == docIndexInt {
|
||||||
log.Debugf("Merging doc %v", currentIndex)
|
log.Debugf("Merging doc %v", currentIndex)
|
||||||
var mergedData map[interface{}]interface{}
|
var mergedData map[interface{}]interface{}
|
||||||
if err := merge(&mergedData, dataBucket, overwriteFlag); err != nil {
|
// merge only works for maps, so put everything in a temporary
|
||||||
|
// map
|
||||||
|
var mapDataBucket = make(map[interface{}]interface{})
|
||||||
|
mapDataBucket["root"] = dataBucket
|
||||||
|
if err := merge(&mergedData, mapDataBucket, overwriteFlag, appendFlag); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
for _, f := range filesToMerge {
|
for _, f := range filesToMerge {
|
||||||
@@ -395,11 +468,12 @@ func mergeProperties(cmd *cobra.Command, args []string) error {
|
|||||||
if err := readData(f, 0, &fileToMerge); err != nil {
|
if err := readData(f, 0, &fileToMerge); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if err := merge(&mergedData, fileToMerge, overwriteFlag); err != nil {
|
mapDataBucket["root"] = fileToMerge
|
||||||
|
if err := merge(&mergedData, mapDataBucket, overwriteFlag, appendFlag); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return mergedData, nil
|
return mergedData["root"], nil
|
||||||
}
|
}
|
||||||
return dataBucket, nil
|
return dataBucket, nil
|
||||||
}
|
}
|
||||||
@@ -476,11 +550,35 @@ func marshalContext(context interface{}) (string, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func safelyRenameFile(from string, to string) {
|
func safelyRenameFile(from string, to string) {
|
||||||
if err := os.Rename(from, to); err != nil {
|
if renameError := os.Rename(from, to); renameError != nil {
|
||||||
log.Errorf("Error renaming from %v to %v", from, to)
|
log.Warningf("Error renaming from %v to %v, attemting to copy contents", from, to)
|
||||||
log.Error(err.Error())
|
log.Warning(renameError.Error())
|
||||||
|
// can't do this rename when running in docker to a file targeted in a mounted volume,
|
||||||
|
// so gracefully degrade to copying the entire contents.
|
||||||
|
if copyError := copyFileContents(from, to); copyError != nil {
|
||||||
|
log.Errorf("Failed copying from %v to %v", from, to)
|
||||||
|
log.Errorf(copyError.Error())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// thanks https://stackoverflow.com/questions/21060945/simple-way-to-copy-a-file-in-golang
|
||||||
|
func copyFileContents(src, dst string) (err error) {
|
||||||
|
in, err := os.Open(src)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer safelyCloseFile(in)
|
||||||
|
out, err := os.Create(dst)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer safelyCloseFile(out)
|
||||||
|
if _, err = io.Copy(out, in); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return out.Sync()
|
||||||
|
}
|
||||||
|
|
||||||
func safelyFlush(writer *bufio.Writer) {
|
func safelyFlush(writer *bufio.Writer) {
|
||||||
if err := writer.Flush(); err != nil {
|
if err := writer.Flush(); err != nil {
|
||||||
@@ -520,8 +618,6 @@ func readStream(filename string, yamlDecoder yamlDecoderFn) error {
|
|||||||
|
|
||||||
func readData(filename string, indexToRead int, parsedData interface{}) error {
|
func readData(filename string, indexToRead int, parsedData interface{}) error {
|
||||||
return readStream(filename, func(decoder *yaml.Decoder) error {
|
return readStream(filename, func(decoder *yaml.Decoder) error {
|
||||||
// naive implementation of document indexing, decodes all the yaml documents
|
|
||||||
// before the docIndex and throws them away.
|
|
||||||
for currentIndex := 0; currentIndex < indexToRead; currentIndex++ {
|
for currentIndex := 0; currentIndex < indexToRead; currentIndex++ {
|
||||||
errorSkipping := decoder.Decode(parsedData)
|
errorSkipping := decoder.Decode(parsedData)
|
||||||
if errorSkipping != nil {
|
if errorSkipping != nil {
|
||||||
|
|||||||
31
yq_test.go
31
yq_test.go
@@ -23,37 +23,6 @@ func TestParseValue(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestRead(t *testing.T) {
|
|
||||||
result, _ := read([]string{"examples/sample.yaml", "b.c"})
|
|
||||||
assertResult(t, 2, result)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestReadMulti(t *testing.T) {
|
|
||||||
docIndex = 1
|
|
||||||
result, _ := read([]string{"examples/multiple_docs.yaml", "another.document"})
|
|
||||||
assertResult(t, "here", result)
|
|
||||||
docIndex = 0
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestReadArray(t *testing.T) {
|
|
||||||
result, _ := read([]string{"examples/sample_array.yaml", "[1]"})
|
|
||||||
assertResult(t, 2, result)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestReadString(t *testing.T) {
|
|
||||||
result, _ := read([]string{"examples/sample_text.yaml"})
|
|
||||||
assertResult(t, "hi", result)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestOrder(t *testing.T) {
|
|
||||||
result, _ := read([]string{"examples/order.yaml"})
|
|
||||||
formattedResult, _ := yamlToString(result)
|
|
||||||
assertResult(t,
|
|
||||||
`version: 3
|
|
||||||
application: MyApp`,
|
|
||||||
formattedResult)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestMultilineString(t *testing.T) {
|
func TestMultilineString(t *testing.T) {
|
||||||
testString := `
|
testString := `
|
||||||
abcd
|
abcd
|
||||||
|
|||||||
Reference in New Issue
Block a user