1
0
mirror of https://github.com/taigrr/yq synced 2025-01-18 04:53:17 -08:00

Compare commits

...

71 Commits

Author SHA1 Message Date
Mike Farah
2bd2a85a4c Fixed trailing empty docs 2020-02-21 11:37:59 +11:00
Mike Farah
ceb76e5c17 Fixed trailing empty docs 2020-02-21 11:34:26 +11:00
Mike Farah
44322f0248 Fixed writing to null document 2020-02-21 11:02:10 +11:00
Mike Farah
0347516d82 Always print new line so wc works properly 2020-02-21 10:29:37 +11:00
Mike Farah
a46386e093 Fixed special characters in path for merging 2020-02-18 20:18:49 +11:00
Mike Farah
f5c3beb159 Added test for https://github.com/mikefarah/yq/issues/361 2020-02-18 20:02:09 +11:00
Mike Farah
9864afc4e7 Fixed empty merge problem 2020-02-18 09:15:46 +11:00
Roberto Mier Escandon
69fae2d9cb Inc Deb version 2020-02-17 09:29:02 +11:00
Mike Farah
83c13ce392 Fixed empty merge problem - need to visit empty arrays and objects 2020-02-13 14:56:58 +11:00
Mike Farah
d83c46eec2 Uncomment line in publish script 2020-02-13 10:22:52 +11:00
Mike Farah
65802f9e0e updated readme 2020-02-12 16:28:24 +11:00
Mike Farah
07309e1685 Inc snapcraft version 2020-02-12 16:27:25 +11:00
Mike Farah
24e906bae6 Fixed numeric map key issue 2020-02-12 15:40:21 +11:00
Mike Farah
f084f2bb23 Inc version for next release 2020-02-12 12:04:41 +11:00
Mike Farah
96a4161a92 Fixed explode anchors for array roots 2020-02-12 11:03:40 +11:00
Mike Farah
5cc01e43bc Can supply value for write from file 2020-02-08 14:04:54 +11:00
Mike Farah
9de2573009 Fixed merge append arrays 2020-02-07 16:32:39 +11:00
Mike Farah
29521f2e3e Simplified when to visit a node 2020-02-07 14:52:37 +11:00
Mike Farah
af5724ba29 Updated readme 2020-02-07 11:28:56 +11:00
Mike Farah
0a39d29c53 Updated readme 2020-02-07 11:26:29 +11:00
Mike Farah
72cd3e4a2a Fixed explode for aliases to scalars 2020-02-07 10:42:07 +11:00
Mike Farah
d40ad9649d Fixed explode for aliases to scalars 2020-02-07 10:09:20 +11:00
Mike Farah
63313ebb02 Merge branch 'coryrc-fix-merge-with-dots' into compare 2020-02-07 09:10:25 +11:00
Mike Farah
de3bfaef60 Merge branch 'fix-merge-with-dots' of git://github.com/coryrc/yq into coryrc-fix-merge-with-dots 2020-02-07 09:09:52 +11:00
Mike Farah
108b5cb093 Fixed explode for simple anchors 2020-02-07 09:08:52 +11:00
Mike Farah
b116f40348 Major version bump for new features 2020-02-06 12:20:51 +11:00
Cory Cross
ea9df0eede Fix path generation when merging file has period in key
The program generates a path for every leaf node in the
file-to-be-merged. It does not escape them if they contain a dot, as
the path-expressions document mentions is necessary.

Add in a test for this condition. Verified it fails without the fix.
2020-02-04 22:37:00 -08:00
Mike Farah
b7dd3e8e0a Added explode test 2020-02-05 15:08:13 +11:00
Mike Farah
dc13fa99f7 wip: explode anchors 2020-02-05 14:10:59 +11:00
Mike Farah
179049a535 Always allow empty 2020-02-04 14:42:08 +11:00
Mike Farah
2fa8b24272 Can merge one file 2020-02-04 14:33:35 +11:00
Mike Farah
f1dbe13f21 Can write and merge into empty files :) 2020-02-04 14:21:54 +11:00
Mike Farah
02258fbaae Fixed deep splatting merge anchors - dont visit twice 2020-02-04 14:10:12 +11:00
Mike Farah
6f0538173b Fix delete adding entries 2020-02-04 09:58:20 +11:00
Mike Farah
6840ea8c78 can set indent levels 2020-02-03 16:56:01 +11:00
Mike Farah
70b88fa778 Pretty print everything test 2020-02-03 16:40:17 +11:00
Mike Farah
bfc1a621c4 Pretty print everything 2020-02-03 16:37:53 +11:00
Mike Farah
166f866f28 Pretty print json 2020-02-03 16:31:03 +11:00
Mike Farah
b3598aaa43 Updated readme 2020-02-03 16:21:00 +11:00
Mike Farah
14ac791eaf Fixed compare output, added tests 2020-02-03 15:35:00 +11:00
Mike Farah
25293a6894 Check write errors 2020-02-03 14:28:38 +11:00
Mike Farah
d828b214cc More powerful compare 2020-02-03 14:15:12 +11:00
Mike Farah
9e47685271 Compare first cut 2020-02-03 13:59:16 +11:00
Mike Farah
699fce9da4 Added default value flag - for printing out a value when reading and there are no matches 2020-02-03 10:13:48 +11:00
Mike Farah
f52de57652 Don't fail when reading an empty file 2020-02-03 09:15:16 +11:00
Mike Farah
b7554e6e76 Pretty print disclaimer 2020-01-31 16:37:24 +11:00
Mike Farah
ec25511f1b Pretty print 2020-01-31 16:35:01 +11:00
Mike Farah
c6a52012ab Prefer download binary 2020-01-31 10:37:27 +11:00
Mike Farah
63ded205e8 Added docs for validate 2020-01-31 10:32:44 +11:00
Mike Farah
d1c1ab0a75 Added validate command 2020-01-30 16:34:43 +11:00
Mike Farah
6ec8386f9e Fixed bad yaml handling 2020-01-30 16:32:28 +11:00
Mike Farah
4dbe3636c2 Splat array is now the fallback instead of parsing int 2020-01-30 15:11:47 +11:00
Mike Farah
4a5bd0ff5b No need to log error 2020-01-30 15:00:27 +11:00
Mike Farah
44f36833cf Fixed delete array pattern matching 2020-01-30 14:55:58 +11:00
Mike Farah
789ea02096 Merge branch 'v3' 2020-01-30 13:01:16 +11:00
Mike Farah
7c27491dd6 Removed user docs 2020-01-30 10:32:34 +11:00
Mike Farah
720cc8f798 Update cli docs 2020-01-30 09:58:21 +11:00
Mike Farah
abda0e38af Removed unused dep 2020-01-22 16:39:41 +11:00
Mike Farah
5cd4c347b0 Updated user docs link 2020-01-22 16:25:52 +11:00
Mike Farah
1a4d8158ba Removed custom value parsing logic 2020-01-20 08:42:08 +11:00
Mike Farah
8a65822b0b Updated docs to include value parsing 2020-01-20 08:35:03 +11:00
Ryan SIU
b7148adf20 #323 Fix the unit test 2020-01-15 14:02:48 +11:00
Ryan SIU
64d38e9f03 #323 Refactor the cobra command with standard structure 2020-01-15 14:02:48 +11:00
Mike Farah
3a387e65be Updated travis ci build 2020-01-15 09:02:06 +11:00
Mike Farah
56ba7c9a43 Updated travis ci build 2020-01-15 09:01:08 +11:00
Mike Farah
d203ec7b56 Accidently changed sample.yaml 2020-01-15 08:55:01 +11:00
Mike Farah
e2f79a3dae bolden contribute disclaimer 2020-01-13 19:45:24 +11:00
Mike Farah
f18c5161e0 Fixed sponge instructions 2020-01-11 16:01:32 +11:00
Mike Farah
eeeeeffd7b Added note about v3 2020-01-11 11:44:02 +11:00
Mike Farah
27604289f4 Log out original error if removing temporary file failed 2019-12-23 12:09:38 +11:00
Mike Farah
3f36a18791 Add readme notice re v3 2019-12-23 10:01:55 +11:00
95 changed files with 2636 additions and 8176 deletions

View File

@@ -1,13 +1,21 @@
# yq
[![Build Status](https://travis-ci.org/mikefarah/yq.svg?branch=master)](https://travis-ci.org/mikefarah/yq) ![Docker Pulls](https://img.shields.io/docker/pulls/mikefarah/yq.svg) ![Github Releases (by Release)](https://img.shields.io/github/downloads/mikefarah/yq/total.svg) ![Go Report](https://goreportcard.com/badge/github.com/mikefarah/yq)
[![Build Status](https://api.travis-ci.com/mikefarah/yq.svg?branch=master)](https://travis-ci.com/mikefarah/yq/) ![Docker Pulls](https://img.shields.io/docker/pulls/mikefarah/yq.svg) ![Github Releases (by Release)](https://img.shields.io/github/downloads/mikefarah/yq/total.svg) ![Go Report](https://goreportcard.com/badge/github.com/mikefarah/yq)
a lightweight and portable command-line YAML processor
The aim of the project is to be the [jq](https://github.com/stedolan/jq) or sed of yaml files.
## New version!
V3 is officially out - if you've been using v2 and want/need to upgrade, checkout the [upgrade guide](https://mikefarah.gitbook.io/yq/upgrading-from-v2).
## Install
### Download the latest binary
[Here](https://github.com/mikefarah/yq/releases/latest)
### On MacOS:
```
brew install yq
@@ -21,27 +29,28 @@ snap install yq
`yq` installs with with [_strict confinement_](https://docs.snapcraft.io/snap-confinement/6233) in snap, this means it doesn't have direct access to root files. To read root files you can:
```
sudo cat /etc/myfile | yq -r - somecommand
sudo cat /etc/myfile | yq r - a.path
```
And to write to a root file you can either use [sponge](https://linux.die.net/man/1/sponge):
```
sudo cat /etc/myfile | yq -r - somecommand | sudo sponge /etc/myfile
sudo cat /etc/myfile | yq w - a.path value | sudo sponge /etc/myfile
```
or write to a temporary file:
```
sudo cat /etc/myfile | yq -r - somecommand | sudo tee /etc/myfile.tmp
sudo cat /etc/myfile | yq w - a.path value | sudo tee /etc/myfile.tmp
sudo mv /etc/myfile.tmp /etc/myfile
rm /etc/myfile.tmp
```
### On Ubuntu 16.04 or higher from Debian package:
```
```sh
sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys CC86BB64
sudo add-apt-repository ppa:rmescandon/yq
sudo apt update
sudo apt install yq -y
```
### or, [Download latest binary](https://github.com/mikefarah/yq/releases/latest) or alternatively:
### Go Get:
```
GO111MODULE=on go get github.com/mikefarah/yq/v3
```
@@ -70,58 +79,56 @@ yq() {
## Features
- Written in portable go, so you can download a lovely dependency free binary
- Deep read a yaml file with a given path
- Update a yaml file given a path
- Update a yaml file given a script file
- [Deep read a yaml file with a given path expression](https://mikefarah.gitbook.io/yq/commands/read#basic)
- [List matching paths of a given path expression](https://mikefarah.gitbook.io/yq/commands/read#path-only)
- Update a yaml file given a [path expression](https://mikefarah.gitbook.io/yq/commands/write-update#basic) or [script file](https://mikefarah.gitbook.io/yq/commands/write-update#basic)
- Update creates any missing entries in the path on the fly
- Create a yaml file given a deep path and value
- Create a yaml file given a script file
- Prefix a path to a yaml file
- Convert from json to yaml
- Convert from yaml to json
- 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 and override previous values.
- Merge multiple yaml files and append array values.
- Supports multiple documents in a single yaml file
- Deeply [compare](https://mikefarah.gitbook.io/yq/commands/compare) yaml files
- Keeps yaml formatting and comments when updating
- [Validate a yaml file](https://mikefarah.gitbook.io/yq/commands/validate)
- Create a yaml file given a [deep path and value](https://mikefarah.gitbook.io/yq/commands/create#creating-a-simple-yaml-file) or a [script file](https://mikefarah.gitbook.io/yq/commands/create#creating-using-a-create-script)
- [Prefix a path to a yaml file](https://mikefarah.gitbook.io/yq/commands/prefix)
- [Convert to/from json to yaml](https://mikefarah.gitbook.io/yq/usage/convert)
- [Pipe data in by using '-'](https://mikefarah.gitbook.io/yq/commands/read#from-stdin)
- [Merge](https://mikefarah.gitbook.io/yq/commands/merge) multiple yaml files with various options for [overriding](https://mikefarah.gitbook.io/yq/commands/merge#overwrite-values) and [appending](https://mikefarah.gitbook.io/yq/commands/merge#append-values-with-arrays)
- Supports multiple documents in a single yaml file for [reading](https://mikefarah.gitbook.io/yq/commands/read#multiple-documents), [writing](https://mikefarah.gitbook.io/yq/commands/write-update#multiple-documents) and [merging](https://mikefarah.gitbook.io/yq/commands/merge#multiple-documents)
## [Usage](http://mikefarah.github.io/yq/)
## [Usage](https://mikefarah.gitbook.io/yq/)
Check out the [documentation](http://mikefarah.github.io/yq/) for more detailed and advanced usage.
Check out the [documentation](https://mikefarah.gitbook.io/yq/) for more detailed and advanced usage.
```
yq is a lightweight and portable command-line YAML processor. It aims to be the jq or sed of yaml files.
Usage:
yq [flags]
yq [command]
Available Commands:
delete yq d [--inplace/-i] [--doc/-d index] sample.yaml a.b.c
compare yq x [--prettyPrint/-P] dataA.yaml dataB.yaml 'b.e(name==fr*).value'
delete yq d [--inplace/-i] [--doc/-d index] sample.yaml 'b.e(name==fred)'
help Help about any command
merge yq m [--inplace/-i] [--doc/-d index] [--overwrite/-x] [--append/-a] sample.yaml sample2.yaml
new yq n [--script/-s script_file] a.b.c newValue
prefix yq p [--inplace/-i] [--doc/-d index] 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] [--doc/-d index] sample.yaml a.b.c newValue
read yq r [--printMode/-p pv] sample.yaml 'b.e(name==fr*).value'
validate yq v sample.yaml
write yq w [--inplace/-i] [--script/-s script_file] [--doc/-d index] sample.yaml 'b.e(name==fr*).value' newValue
Flags:
-h, --help help for yq
-t, --trim trim yaml output (default true)
-v, --verbose verbose mode
-V, --version Print version information and quit
-h, --help help for yq
-I, --indent int sets indent level for output (default 2)
-P, --prettyPrint pretty print
-j, --tojson output as json. By default it prints a json document in one line, use the prettyPrint flag to print a formatted doc.
-v, --verbose verbose mode
-V, --version Print version information and quit
Use "yq [command] --help" for more information about a command.
```
## Contribute
1. `scripts/devtools.sh`
2. `make [local] vendor`
3. add unit tests
4. apply changes to go.mod
5. `make [local] build`
6. If required, update the user documentation
- Update README.md and/or documentation under the mkdocs folder
- `make [local] build-docs`
- browse to docs/index.html and check your changes
7. profit

File diff suppressed because it is too large Load Diff

76
cmd/compare.go Normal file
View File

@@ -0,0 +1,76 @@
package cmd
import (
"bufio"
"bytes"
"strings"
"github.com/kylelemons/godebug/diff"
"github.com/mikefarah/yq/v3/pkg/yqlib"
errors "github.com/pkg/errors"
"github.com/spf13/cobra"
)
func createCompareCmd() *cobra.Command {
var cmdCompare = &cobra.Command{
Use: "compare [yaml_file_a] [yaml_file_b]",
Aliases: []string{"x"},
Short: "yq x [--prettyPrint/-P] dataA.yaml dataB.yaml 'b.e(name==fr*).value'",
Example: `
yq x - data2.yml # reads from stdin
yq x -pp dataA.yaml dataB.yaml '**' # compare paths
yq x -d1 dataA.yaml dataB.yaml 'a.b.c'
`,
Long: "Deeply compares two yaml files, prints the difference. Use with prettyPrint flag to ignore formatting differences.",
RunE: compareDocuments,
}
cmdCompare.PersistentFlags().StringVarP(&docIndex, "doc", "d", "0", "process document index number (0 based, * for all documents)")
cmdCompare.PersistentFlags().StringVarP(&printMode, "printMode", "p", "v", "print mode (v (values, default), p (paths), pv (path and value pairs)")
cmdCompare.PersistentFlags().StringVarP(&defaultValue, "defaultValue", "D", "", "default value printed when there are no results")
return cmdCompare
}
func compareDocuments(cmd *cobra.Command, args []string) error {
var path = ""
if len(args) < 2 {
return errors.New("Must provide at 2 yaml files")
} else if len(args) > 2 {
path = args[2]
}
var updateAll, docIndexInt, errorParsingDocIndex = parseDocumentIndex()
if errorParsingDocIndex != nil {
return errorParsingDocIndex
}
var matchingNodesA []*yqlib.NodeContext
var matchingNodesB []*yqlib.NodeContext
var errorDoingThings error
matchingNodesA, errorDoingThings = readYamlFile(args[0], path, updateAll, docIndexInt)
if errorDoingThings != nil {
return errorDoingThings
}
matchingNodesB, errorDoingThings = readYamlFile(args[1], path, updateAll, docIndexInt)
if errorDoingThings != nil {
return errorDoingThings
}
var dataBufferA bytes.Buffer
var dataBufferB bytes.Buffer
errorDoingThings = printResults(matchingNodesA, bufio.NewWriter(&dataBufferA))
if errorDoingThings != nil {
return errorDoingThings
}
errorDoingThings = printResults(matchingNodesB, bufio.NewWriter(&dataBufferB))
if errorDoingThings != nil {
return errorDoingThings
}
cmd.Print(diff.Diff(strings.TrimSuffix(dataBufferA.String(), "\n"), strings.TrimSuffix(dataBufferB.String(), "\n")))
cmd.Print("\n")
return nil
}

26
cmd/constant.go Normal file
View File

@@ -0,0 +1,26 @@
package cmd
import (
"github.com/mikefarah/yq/v3/pkg/yqlib"
logging "gopkg.in/op/go-logging.v1"
)
var customTag = ""
var printMode = "v"
var writeInplace = false
var writeScript = ""
var sourceYamlFile = ""
var outputToJSON = false
var prettyPrint = false
var explodeAnchors = false
var defaultValue = ""
var indent = 2
var overwriteFlag = false
var autoCreateFlag = true
var appendFlag = false
var verbose = false
var version = false
var docIndex = "0"
var log = logging.MustGetLogger("yq")
var lib = yqlib.NewYqLib()
var valueParser = yqlib.NewValueParser()

41
cmd/delete.go Normal file
View File

@@ -0,0 +1,41 @@
package cmd
import (
"github.com/mikefarah/yq/v3/pkg/yqlib"
errors "github.com/pkg/errors"
"github.com/spf13/cobra"
)
func createDeleteCmd() *cobra.Command {
var cmdDelete = &cobra.Command{
Use: "delete [yaml_file] [path_expression]",
Aliases: []string{"d"},
Short: "yq d [--inplace/-i] [--doc/-d index] sample.yaml 'b.e(name==fred)'",
Example: `
yq delete things.yaml 'a.b.c'
yq delete things.yaml 'a.*.c'
yq delete things.yaml 'a.(child.subchild==co*).c'
yq delete things.yaml 'a.**'
yq delete --inplace things.yaml 'a.b.c'
yq delete --inplace -- things.yaml '--key-starting-with-dash' # need to use '--' to stop processing arguments as flags
yq d -i things.yaml 'a.b.c'
`,
Long: `Deletes the nodes matching the given path expression from the YAML file.
Outputs to STDOUT unless the inplace flag is used, in which case the file is updated instead.
`,
RunE: deleteProperty,
}
cmdDelete.PersistentFlags().BoolVarP(&writeInplace, "inplace", "i", false, "update the yaml file inplace")
cmdDelete.PersistentFlags().StringVarP(&docIndex, "doc", "d", "0", "process document index number (0 based, * for all documents)")
return cmdDelete
}
func deleteProperty(cmd *cobra.Command, args []string) error {
if len(args) < 2 {
return errors.New("Must provide <filename> <path_to_delete>")
}
var updateCommands []yqlib.UpdateCommand = make([]yqlib.UpdateCommand, 1)
updateCommands[0] = yqlib.UpdateCommand{Command: "delete", Path: args[1]}
return updateDoc(args[0], updateCommands, cmd.OutOrStdout())
}

74
cmd/merge.go Normal file
View File

@@ -0,0 +1,74 @@
package cmd
import (
"github.com/mikefarah/yq/v3/pkg/yqlib"
errors "github.com/pkg/errors"
"github.com/spf13/cobra"
yaml "gopkg.in/yaml.v3"
)
func createMergeCmd() *cobra.Command {
var cmdMerge = &cobra.Command{
Use: "merge [initial_yaml_file] [additional_yaml_file]...",
Aliases: []string{"m"},
Short: "yq m [--inplace/-i] [--doc/-d index] [--overwrite/-x] [--append/-a] sample.yaml sample2.yaml",
Example: `
yq merge things.yaml other.yaml
yq merge --inplace things.yaml other.yaml
yq m -i things.yaml other.yaml
yq m --overwrite things.yaml other.yaml
yq m -i -x things.yaml other.yaml
yq m -i -a things.yaml other.yaml
yq m -i --autocreate=false things.yaml other.yaml
`,
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.
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.
`,
RunE: mergeProperties,
}
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(&autoCreateFlag, "autocreate", "c", true, "automatically create any missing entries")
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
}
/*
* We don't deeply traverse arrays when appending a merge, instead we want to
* append the entire array element.
*/
func createReadFunctionForMerge() func(*yaml.Node) ([]*yqlib.NodeContext, error) {
return func(dataBucket *yaml.Node) ([]*yqlib.NodeContext, error) {
return lib.Get(dataBucket, "**", !appendFlag)
}
}
func mergeProperties(cmd *cobra.Command, args []string) error {
var updateCommands []yqlib.UpdateCommand = make([]yqlib.UpdateCommand, 0)
if len(args) < 1 {
return errors.New("Must provide at least 1 yaml file")
}
if len(args) > 1 {
// first generate update commands from the file
var filesToMerge = args[1:]
for _, fileToMerge := range filesToMerge {
matchingNodes, errorProcessingFile := doReadYamlFile(fileToMerge, createReadFunctionForMerge(), false, 0)
if errorProcessingFile != nil {
return errorProcessingFile
}
for _, matchingNode := range matchingNodes {
mergePath := lib.MergePathStackToString(matchingNode.PathStack, appendFlag)
updateCommands = append(updateCommands, yqlib.UpdateCommand{Command: "update", Path: mergePath, Value: matchingNode.Node, Overwrite: overwriteFlag})
}
}
}
return updateDoc(args[0], updateCommands, cmd.OutOrStdout())
}

54
cmd/new.go Normal file
View File

@@ -0,0 +1,54 @@
package cmd
import (
"github.com/spf13/cobra"
yaml "gopkg.in/yaml.v3"
)
func createNewCmd() *cobra.Command {
var cmdNew = &cobra.Command{
Use: "new [path] [value]",
Aliases: []string{"n"},
Short: "yq n [--script/-s script_file] a.b.c newValue",
Example: `
yq new 'a.b.c' cat
yq n 'a.b.c' --tag '!!str' true # force 'true' to be interpreted as a string instead of bool
yq n 'a.b[+]' cat
yq n -- '--key-starting-with-dash' cat # need to use '--' to stop processing arguments as flags
yq n --script create_script.yaml
`,
Long: `Creates a new yaml w.r.t the given path and value.
Outputs to STDOUT
Create Scripts:
Note that you can give a create script to perform more sophisticated yaml. This follows the same format as the update script.
`,
RunE: newProperty,
}
cmdNew.PersistentFlags().StringVarP(&writeScript, "script", "s", "", "yaml script for creating yaml")
cmdNew.PersistentFlags().StringVarP(&customTag, "tag", "t", "", "set yaml tag (e.g. !!int)")
return cmdNew
}
func newProperty(cmd *cobra.Command, args []string) error {
var updateCommands, updateCommandsError = readUpdateCommands(args, 2, "Must provide <path_to_update> <value>")
if updateCommandsError != nil {
return updateCommandsError
}
newNode := lib.New(updateCommands[0].Path)
for _, updateCommand := range updateCommands {
errorUpdating := lib.Update(&newNode, updateCommand, true)
if errorUpdating != nil {
return errorUpdating
}
}
var encoder = yaml.NewEncoder(cmd.OutOrStdout())
encoder.SetIndent(2)
errorEncoding := encoder.Encode(&newNode)
encoder.Close()
return errorEncoding
}

50
cmd/prefix.go Normal file
View File

@@ -0,0 +1,50 @@
package cmd
import (
"github.com/mikefarah/yq/v3/pkg/yqlib"
errors "github.com/pkg/errors"
"github.com/spf13/cobra"
yaml "gopkg.in/yaml.v3"
)
func createPrefixCmd() *cobra.Command {
var cmdPrefix = &cobra.Command{
Use: "prefix [yaml_file] [path]",
Aliases: []string{"p"},
Short: "yq p [--inplace/-i] [--doc/-d index] sample.yaml a.b.c",
Example: `
yq prefix things.yaml 'a.b.c'
yq prefix --inplace things.yaml 'a.b.c'
yq prefix --inplace -- things.yaml '--key-starting-with-dash' # need to use '--' to stop processing arguments as flags
yq p -i things.yaml 'a.b.c'
yq p --doc 2 things.yaml 'a.b.d'
yq p -d2 things.yaml 'a.b.d'
`,
Long: `Prefixes w.r.t to the yaml file at the given path.
Outputs to STDOUT unless the inplace flag is used, in which case the file is updated instead.
`,
RunE: prefixProperty,
}
cmdPrefix.PersistentFlags().BoolVarP(&writeInplace, "inplace", "i", false, "update the yaml file inplace")
cmdPrefix.PersistentFlags().StringVarP(&docIndex, "doc", "d", "0", "process document index number (0 based, * for all documents)")
return cmdPrefix
}
func prefixProperty(cmd *cobra.Command, args []string) error {
if len(args) < 2 {
return errors.New("Must provide <filename> <prefixed_path>")
}
updateCommand := yqlib.UpdateCommand{Command: "update", Path: args[1]}
log.Debugf("args %v", args)
var updateAll, docIndexInt, errorParsingDocIndex = parseDocumentIndex()
if errorParsingDocIndex != nil {
return errorParsingDocIndex
}
var updateData = func(dataBucket *yaml.Node, currentIndex int) error {
return prefixDocument(updateAll, docIndexInt, currentIndex, dataBucket, updateCommand)
}
return readAndUpdate(cmd.OutOrStdout(), args[0], updateData)
}

54
cmd/read.go Normal file
View File

@@ -0,0 +1,54 @@
package cmd
import (
errors "github.com/pkg/errors"
"github.com/spf13/cobra"
)
func createReadCmd() *cobra.Command {
var cmdRead = &cobra.Command{
Use: "read [yaml_file] [path_expression]",
Aliases: []string{"r"},
Short: "yq r [--printMode/-p pv] sample.yaml 'b.e(name==fr*).value'",
Example: `
yq read things.yaml 'a.b.c'
yq r - 'a.b.c' # reads from stdin
yq r things.yaml 'a.*.c'
yq r things.yaml 'a.**.c' # deep splat
yq r things.yaml 'a.(child.subchild==co*).c'
yq r -d1 things.yaml 'a.array[0].blah'
yq r things.yaml 'a.array[*].blah'
yq r -- things.yaml '--key-starting-with-dashes.blah'
`,
Long: "Outputs the value of the given path in the yaml file to STDOUT",
RunE: readProperty,
}
cmdRead.PersistentFlags().StringVarP(&docIndex, "doc", "d", "0", "process document index number (0 based, * for all documents)")
cmdRead.PersistentFlags().StringVarP(&printMode, "printMode", "p", "v", "print mode (v (values, default), p (paths), pv (path and value pairs)")
cmdRead.PersistentFlags().StringVarP(&defaultValue, "defaultValue", "D", "", "default value printed when there are no results")
cmdRead.PersistentFlags().BoolVarP(&explodeAnchors, "explodeAnchors", "X", false, "explode anchors")
return cmdRead
}
func readProperty(cmd *cobra.Command, args []string) error {
var path = ""
if len(args) < 1 {
return errors.New("Must provide filename")
} else if len(args) > 1 {
path = args[1]
}
var updateAll, docIndexInt, errorParsingDocIndex = parseDocumentIndex()
if errorParsingDocIndex != nil {
return errorParsingDocIndex
}
matchingNodes, errorReadingStream := readYamlFile(args[0], path, updateAll, docIndexInt)
if errorReadingStream != nil {
return errorReadingStream
}
return printResults(matchingNodes, cmd.OutOrStdout())
}

60
cmd/root.go Normal file
View File

@@ -0,0 +1,60 @@
package cmd
import (
"os"
"github.com/spf13/cobra"
logging "gopkg.in/op/go-logging.v1"
)
func New() *cobra.Command {
var rootCmd = &cobra.Command{
Use: "yq",
Short: "yq is a lightweight and portable command-line YAML processor.",
Long: `yq is a lightweight and portable command-line YAML processor. It aims to be the jq or sed of yaml files.`,
RunE: func(cmd *cobra.Command, args []string) error {
if version {
cmd.Print(GetVersionDisplay())
return nil
}
cmd.Println(cmd.UsageString())
return nil
},
PersistentPreRun: func(cmd *cobra.Command, args []string) {
var format = logging.MustStringFormatter(
`%{color}%{time:15:04:05} %{shortfunc} [%{level:.4s}]%{color:reset} %{message}`,
)
var backend = logging.AddModuleLevel(
logging.NewBackendFormatter(logging.NewLogBackend(os.Stderr, "", 0), format))
if verbose {
backend.SetLevel(logging.DEBUG, "")
} else {
backend.SetLevel(logging.ERROR, "")
}
logging.SetBackend(backend)
},
}
rootCmd.PersistentFlags().BoolVarP(&verbose, "verbose", "v", false, "verbose mode")
rootCmd.PersistentFlags().BoolVarP(&outputToJSON, "tojson", "j", false, "output as json. By default it prints a json document in one line, use the prettyPrint flag to print a formatted doc.")
rootCmd.PersistentFlags().BoolVarP(&prettyPrint, "prettyPrint", "P", false, "pretty print")
rootCmd.PersistentFlags().IntVarP(&indent, "indent", "I", 2, "sets indent level for output")
rootCmd.Flags().BoolVarP(&version, "version", "V", false, "Print version information and quit")
rootCmd.AddCommand(
createReadCmd(),
createCompareCmd(),
createValidateCmd(),
createWriteCmd(),
createPrefixCmd(),
createDeleteCmd(),
createNewCmd(),
createMergeCmd(),
)
rootCmd.SetOutput(os.Stdout)
return rootCmd
}

470
cmd/utils.go Normal file
View File

@@ -0,0 +1,470 @@
package cmd
import (
"bufio"
"fmt"
"io"
"io/ioutil"
"os"
"strconv"
"github.com/mikefarah/yq/v3/pkg/yqlib"
errors "github.com/pkg/errors"
yaml "gopkg.in/yaml.v3"
)
type readDataFn func(dataBucket *yaml.Node) ([]*yqlib.NodeContext, error)
func createReadFunction(path string) func(*yaml.Node) ([]*yqlib.NodeContext, error) {
return func(dataBucket *yaml.Node) ([]*yqlib.NodeContext, error) {
return lib.Get(dataBucket, path, true)
}
}
func readYamlFile(filename string, path string, updateAll bool, docIndexInt int) ([]*yqlib.NodeContext, error) {
return doReadYamlFile(filename, createReadFunction(path), updateAll, docIndexInt)
}
func doReadYamlFile(filename string, readFn readDataFn, updateAll bool, docIndexInt int) ([]*yqlib.NodeContext, error) {
var matchingNodes []*yqlib.NodeContext
var currentIndex = 0
var errorReadingStream = readStream(filename, func(decoder *yaml.Decoder) error {
for {
var dataBucket yaml.Node
errorReading := decoder.Decode(&dataBucket)
if errorReading == io.EOF {
return handleEOF(updateAll, docIndexInt, currentIndex)
} else if errorReading != nil {
return errorReading
}
var errorParsing error
matchingNodes, errorParsing = appendDocument(matchingNodes, dataBucket, readFn, updateAll, docIndexInt, currentIndex)
if errorParsing != nil {
return errorParsing
}
if !updateAll && currentIndex == docIndexInt {
log.Debug("all done")
return nil
}
currentIndex = currentIndex + 1
}
})
return matchingNodes, errorReadingStream
}
func handleEOF(updateAll bool, docIndexInt int, currentIndex int) error {
log.Debugf("done %v / %v", currentIndex, docIndexInt)
if !updateAll && currentIndex <= docIndexInt && docIndexInt != 0 {
return fmt.Errorf("Could not process document index %v as there are only %v document(s)", docIndex, currentIndex)
}
return nil
}
func appendDocument(originalMatchingNodes []*yqlib.NodeContext, dataBucket yaml.Node, readFn readDataFn, updateAll bool, docIndexInt int, currentIndex int) ([]*yqlib.NodeContext, error) {
log.Debugf("processing document %v - requested index %v", currentIndex, docIndexInt)
yqlib.DebugNode(&dataBucket)
if !updateAll && currentIndex != docIndexInt {
return originalMatchingNodes, nil
}
log.Debugf("reading in document %v", currentIndex)
matchingNodes, errorParsing := readFn(&dataBucket)
if errorParsing != nil {
return nil, errors.Wrapf(errorParsing, "Error reading path in document index %v", currentIndex)
}
return append(originalMatchingNodes, matchingNodes...), nil
}
func printValue(node *yaml.Node, writer io.Writer) error {
if node.Kind == yaml.ScalarNode {
_, errorWriting := writer.Write([]byte(node.Value + "\n"))
return errorWriting
}
return printNode(node, writer)
}
func printNode(node *yaml.Node, writer io.Writer) error {
var encoder yqlib.Encoder
if outputToJSON {
encoder = yqlib.NewJsonEncoder(writer, prettyPrint, indent)
} else {
encoder = yqlib.NewYamlEncoder(writer, indent)
}
return encoder.Encode(node)
}
func setStyle(matchingNodes []*yqlib.NodeContext, style yaml.Style) {
for _, nodeContext := range matchingNodes {
updateStyleOfNode(nodeContext.Node, style)
}
}
func updateStyleOfNode(node *yaml.Node, style yaml.Style) {
node.Style = style
for _, child := range node.Content {
updateStyleOfNode(child, style)
}
}
func writeString(writer io.Writer, txt string) error {
_, errorWriting := writer.Write([]byte(txt))
return errorWriting
}
func explode(matchingNodes []*yqlib.NodeContext) error {
log.Debug("exploding nodes")
for _, nodeContext := range matchingNodes {
var targetNode = yaml.Node{Kind: nodeContext.Node.Kind}
explodedNodes, errorRetrieving := lib.Get(nodeContext.Node, "**", true)
if errorRetrieving != nil {
return errorRetrieving
}
for _, matchingNode := range explodedNodes {
mergePath := lib.MergePathStackToString(matchingNode.PathStack, appendFlag)
updateCommand := yqlib.UpdateCommand{Command: "update", Path: mergePath, Value: matchingNode.Node, Overwrite: overwriteFlag}
errorUpdating := lib.Update(&targetNode, updateCommand, true)
if errorUpdating != nil {
return errorUpdating
}
}
nodeContext.Node = &targetNode
}
log.Debug("done exploding nodes")
return nil
}
func printResults(matchingNodes []*yqlib.NodeContext, writer io.Writer) error {
if prettyPrint {
setStyle(matchingNodes, 0)
}
//always explode anchors when printing json
if explodeAnchors || outputToJSON {
errorExploding := explode(matchingNodes)
if errorExploding != nil {
return errorExploding
}
}
bufferedWriter := bufio.NewWriter(writer)
defer safelyFlush(bufferedWriter)
if len(matchingNodes) == 0 {
log.Debug("no matching results, nothing to print")
if defaultValue != "" {
return writeString(bufferedWriter, defaultValue)
}
return nil
}
var errorWriting error
for _, mappedDoc := range matchingNodes {
switch printMode {
case "p":
errorWriting = writeString(bufferedWriter, lib.PathStackToString(mappedDoc.PathStack)+"\n")
if errorWriting != nil {
return errorWriting
}
case "pv", "vp":
// put it into a node and print that.
var parentNode = yaml.Node{Kind: yaml.MappingNode}
parentNode.Content = make([]*yaml.Node, 2)
parentNode.Content[0] = &yaml.Node{Kind: yaml.ScalarNode, Value: lib.PathStackToString(mappedDoc.PathStack)}
parentNode.Content[1] = mappedDoc.Node
if err := printValue(&parentNode, bufferedWriter); err != nil {
return err
}
default:
if err := printValue(mappedDoc.Node, bufferedWriter); err != nil {
return err
}
}
}
return 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 *yaml.Node, currentIndex int) error
func isNullDocument(dataBucket *yaml.Node) bool {
return dataBucket.Kind == yaml.DocumentNode && (len(dataBucket.Content) == 0 ||
dataBucket.Content[0].Kind == yaml.ScalarNode && dataBucket.Content[0].Tag == "!!null")
}
func mapYamlDecoder(updateData updateDataFn, encoder yqlib.Encoder) yamlDecoderFn {
return func(decoder *yaml.Decoder) error {
var dataBucket yaml.Node
var errorReading error
var errorWriting error
var errorUpdating error
var currentIndex = 0
var updateAll, docIndexInt, errorParsingDocIndex = parseDocumentIndex()
if errorParsingDocIndex != nil {
return errorParsingDocIndex
}
for {
log.Debugf("Read doc %v", currentIndex)
errorReading = decoder.Decode(&dataBucket)
if errorReading == io.EOF && docIndexInt == 0 && currentIndex == 0 {
//empty document, lets just make one
dataBucket = yaml.Node{Kind: yaml.DocumentNode, Content: make([]*yaml.Node, 1)}
child := yaml.Node{Kind: yaml.MappingNode}
dataBucket.Content[0] = &child
} else if isNullDocument(&dataBucket) && (updateAll || docIndexInt == currentIndex) {
child := yaml.Node{Kind: yaml.MappingNode}
dataBucket.Content[0] = &child
} else if errorReading == io.EOF {
if !updateAll && currentIndex <= docIndexInt {
return fmt.Errorf("asked to process document index %v but there are only %v document(s)", docIndex, currentIndex)
}
return nil
} else if errorReading != nil {
return errors.Wrapf(errorReading, "Error reading document at index %v, %v", currentIndex, errorReading)
}
errorUpdating = updateData(&dataBucket, currentIndex)
if errorUpdating != nil {
return errors.Wrapf(errorUpdating, "Error updating document at index %v", currentIndex)
}
if prettyPrint {
updateStyleOfNode(&dataBucket, 0)
}
errorWriting = encoder.Encode(&dataBucket)
if errorWriting != nil {
return errors.Wrapf(errorWriting, "Error writing document at index %v, %v", currentIndex, errorWriting)
}
currentIndex = currentIndex + 1
}
}
}
func prefixDocument(updateAll bool, docIndexInt int, currentIndex int, dataBucket *yaml.Node, updateCommand yqlib.UpdateCommand) error {
if updateAll || currentIndex == docIndexInt {
log.Debugf("Prefixing document %v", currentIndex)
yqlib.DebugNode(dataBucket)
updateCommand.Value = dataBucket.Content[0]
dataBucket.Content = make([]*yaml.Node, 1)
newNode := lib.New(updateCommand.Path)
dataBucket.Content[0] = &newNode
errorUpdating := lib.Update(dataBucket, updateCommand, true)
if errorUpdating != nil {
return errorUpdating
}
}
return nil
}
func updateDoc(inputFile string, updateCommands []yqlib.UpdateCommand, writer io.Writer) error {
var updateAll, docIndexInt, errorParsingDocIndex = parseDocumentIndex()
if errorParsingDocIndex != nil {
return errorParsingDocIndex
}
var updateData = func(dataBucket *yaml.Node, currentIndex int) error {
if updateAll || currentIndex == docIndexInt {
log.Debugf("Updating doc %v", currentIndex)
for _, updateCommand := range updateCommands {
log.Debugf("Processing update to Path %v", updateCommand.Path)
errorUpdating := lib.Update(dataBucket, updateCommand, autoCreateFlag)
if errorUpdating != nil {
return errorUpdating
}
}
}
return nil
}
return readAndUpdate(writer, inputFile, updateData)
}
func readAndUpdate(stdOut io.Writer, inputFile string, updateData updateDataFn) error {
var destination io.Writer
var destinationName string
if writeInplace {
info, err := os.Stat(inputFile)
if err != nil {
return err
}
tempFile, err := ioutil.TempFile("", "temp")
if err != nil {
return err
}
destinationName = tempFile.Name()
err = os.Chmod(destinationName, info.Mode())
if err != nil {
return err
}
destination = tempFile
defer func() {
safelyCloseFile(tempFile)
safelyRenameFile(tempFile.Name(), inputFile)
}()
} else {
destination = stdOut
destinationName = "Stdout"
}
log.Debugf("Writing to %v from %v", destinationName, inputFile)
bufferedWriter := bufio.NewWriter(destination)
defer safelyFlush(bufferedWriter)
var encoder yqlib.Encoder
if outputToJSON {
encoder = yqlib.NewJsonEncoder(bufferedWriter, prettyPrint, indent)
} else {
encoder = yqlib.NewYamlEncoder(bufferedWriter, indent)
}
return readStream(inputFile, mapYamlDecoder(updateData, encoder))
}
type updateCommandParsed struct {
Command string
Path string
Value yaml.Node
}
func readUpdateCommands(args []string, expectedArgs int, badArgsMessage string) ([]yqlib.UpdateCommand, error) {
var updateCommands []yqlib.UpdateCommand = make([]yqlib.UpdateCommand, 0)
if writeScript != "" {
var parsedCommands = make([]updateCommandParsed, 0)
err := readData(writeScript, 0, &parsedCommands)
if err != nil && err != io.EOF {
return nil, err
}
log.Debugf("Read write commands file '%v'", parsedCommands)
for index := range parsedCommands {
parsedCommand := parsedCommands[index]
updateCommand := yqlib.UpdateCommand{Command: parsedCommand.Command, Path: parsedCommand.Path, Value: &parsedCommand.Value, Overwrite: true}
updateCommands = append(updateCommands, updateCommand)
}
log.Debugf("Read write commands file '%v'", updateCommands)
} else if sourceYamlFile != "" && len(args) == expectedArgs-1 {
log.Debugf("Reading value from %v", sourceYamlFile)
var value yaml.Node
err := readData(sourceYamlFile, 0, &value)
if err != nil && err != io.EOF {
return nil, err
}
log.Debug("args %v", args[expectedArgs-2])
updateCommands = make([]yqlib.UpdateCommand, 1)
updateCommands[0] = yqlib.UpdateCommand{Command: "update", Path: args[expectedArgs-2], Value: value.Content[0], Overwrite: true}
} else if len(args) < expectedArgs {
return nil, errors.New(badArgsMessage)
} else {
updateCommands = make([]yqlib.UpdateCommand, 1)
log.Debug("args %v", args)
log.Debug("path %v", args[expectedArgs-2])
log.Debug("Value %v", args[expectedArgs-1])
updateCommands[0] = yqlib.UpdateCommand{Command: "update", Path: args[expectedArgs-2], Value: valueParser.Parse(args[expectedArgs-1], customTag), Overwrite: true}
}
return updateCommands, nil
}
func safelyRenameFile(from string, to string) {
if renameError := os.Rename(from, to); renameError != nil {
log.Debugf("Error renaming from %v to %v, attempting to copy contents", from, to)
log.Debug(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.Error(copyError.Error())
} else {
removeErr := os.Remove(from)
if removeErr != nil {
log.Errorf("failed removing original file: %s", from)
}
}
}
}
// 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) // nolint gosec
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) {
if err := writer.Flush(); err != nil {
log.Error("Error flushing writer!")
log.Error(err.Error())
}
}
func safelyCloseFile(file *os.File) {
err := file.Close()
if err != nil {
log.Error("Error closing file!")
log.Error(err.Error())
}
}
type yamlDecoderFn func(*yaml.Decoder) error
func readStream(filename string, yamlDecoder yamlDecoderFn) error {
if filename == "" {
return errors.New("Must provide filename")
}
var stream io.Reader
if filename == "-" {
stream = bufio.NewReader(os.Stdin)
} else {
file, err := os.Open(filename) // nolint gosec
if err != nil {
return err
}
defer safelyCloseFile(file)
stream = file
}
return yamlDecoder(yaml.NewDecoder(stream))
}
func readData(filename string, indexToRead int, parsedData interface{}) error {
return readStream(filename, func(decoder *yaml.Decoder) error {
for currentIndex := 0; currentIndex < indexToRead; currentIndex++ {
errorSkipping := decoder.Decode(parsedData)
if errorSkipping != nil {
return errors.Wrapf(errorSkipping, "Error processing document at index %v, %v", currentIndex, errorSkipping)
}
}
return decoder.Decode(parsedData)
})
}

37
cmd/validate.go Normal file
View File

@@ -0,0 +1,37 @@
package cmd
import (
errors "github.com/pkg/errors"
"github.com/spf13/cobra"
)
func createValidateCmd() *cobra.Command {
var cmdRead = &cobra.Command{
Use: "validate [yaml_file]",
Aliases: []string{"v"},
Short: "yq v sample.yaml",
Example: `
yq v - # reads from stdin
`,
RunE: validateProperty,
SilenceUsage: true,
SilenceErrors: true,
}
cmdRead.PersistentFlags().StringVarP(&docIndex, "doc", "d", "0", "process document index number (0 based, * for all documents)")
return cmdRead
}
func validateProperty(cmd *cobra.Command, args []string) error {
if len(args) < 1 {
return errors.New("Must provide filename")
}
var updateAll, docIndexInt, errorParsingDocIndex = parseDocumentIndex()
if errorParsingDocIndex != nil {
return errorParsingDocIndex
}
_, errorReadingStream := readYamlFile(args[0], "", updateAll, docIndexInt)
return errorReadingStream
}

View File

@@ -1,4 +1,4 @@
package main
package cmd
import (
"fmt"
@@ -11,12 +11,12 @@ var (
GitDescribe string
// Version is main version number that is being run at the moment.
Version = "3.0.0"
Version = "3.1.2"
// 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
// such as "dev" (in development), "beta", "rc1", etc.
VersionPrerelease = "beta"
VersionPrerelease = ""
)
// ProductName is the name of the product

View File

@@ -1,4 +1,4 @@
package main
package cmd
import "testing"

58
cmd/write.go Normal file
View File

@@ -0,0 +1,58 @@
package cmd
import (
"github.com/spf13/cobra"
)
func createWriteCmd() *cobra.Command {
var cmdWrite = &cobra.Command{
Use: "write [yaml_file] [path_expression] [value]",
Aliases: []string{"w"},
Short: "yq w [--inplace/-i] [--script/-s script_file] [--doc/-d index] sample.yaml 'b.e(name==fr*).value' newValue",
Example: `
yq write things.yaml 'a.b.c' true
yq write things.yaml 'a.*.c' true
yq write things.yaml 'a.**' true
yq write things.yaml 'a.(child.subchild==co*).c' true
yq write things.yaml 'a.b.c' --tag '!!str' true # force 'true' to be interpreted as a string instead of bool
yq write things.yaml 'a.b.c' --tag '!!float' 3
yq write --inplace -- things.yaml 'a.b.c' '--cat' # need to use '--' to stop processing arguments as flags
yq w -i things.yaml 'a.b.c' cat
yq w -i -s update_script.yaml things.yaml
yq w things.yaml 'a.b.d[+]' foo # appends a new node to the 'd' array
yq w --doc 2 things.yaml 'a.b.d[+]' foo # updates the 3rd document of the yaml file
`,
Long: `Updates the yaml file w.r.t the given path and value.
Outputs to STDOUT unless the inplace flag is used, in which case the file is updated instead.
Append value to array adds the value to the end of array.
Update Scripts:
Note that you can give an update script to perform more sophisticated update. Update script
format is list of update commands (update or delete) like so:
---
- command: update
path: b.c
value:
#great
things: frog # wow!
- command: delete
path: b.d
`,
RunE: writeProperty,
}
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(&sourceYamlFile, "from", "f", "", "yaml file for updating yaml (as-is)")
cmdWrite.PersistentFlags().StringVarP(&customTag, "tag", "t", "", "set yaml tag (e.g. !!int)")
cmdWrite.PersistentFlags().StringVarP(&docIndex, "doc", "d", "0", "process document index number (0 based, * for all documents)")
return cmdWrite
}
func writeProperty(cmd *cobra.Command, args []string) error {
var updateCommands, updateCommandsError = readUpdateCommands(args, 3, "Must provide <filename> <path_to_update> <value>")
if updateCommandsError != nil {
return updateCommandsError
}
return updateDoc(args[0], updateCommands, cmd.OutOrStdout())
}

13
debian/changelog vendored
View File

@@ -1,3 +1,16 @@
yq (3.1.1) eoan; urgency=medium
* Keeps yaml comments and formatting, can specify yaml tags when updating.
* Handles anchors! https://github.com/mikefarah/yq/issues/310, https://github.com/mikefarah/yq/issues/178
* Can print out matching paths and values when splatting https://github.com/mikefarah/yq/issues/20
* JSON output works for all commands! Yaml files with multiple documents are printed out as one JSON document per line.
* Deep splat (**) to match arbitrary paths
* Update scripts file format has changed to be more powerful
* Reading and splatting, matching results are printed once per line
* Bugfixing
-- Roberto Mier Escandon <rmescandon@gmail.com> Tue, 11 Feb 2020 22:18:24 +0100
yq (2.2-1) bionic; urgency=medium
* Added Windows support for the "--inplace" command flag

21
debian/control vendored
View File

@@ -1,22 +1,23 @@
Source: yq
Section: devel
Priority: extra
Priority: optional
Maintainer: Roberto Mier Escandón <rmescandon@gmail.com>
Build-Depends: debhelper (>= 9),
dh-golang,
golang-1.10-go,
Build-Depends: debhelper (>=10),
dh-golang (>=1.34),
golang-1.13,
dpkg-dev,
rsync
Standards-Version: 3.9.6
Homepage: https://github.com/mikefarah/yq.git
Vcs-Browser: https://github.com/mikefarah/yq.git
Vcs-Git: https://github.com/mikefarah/yq.git
XS-Go-Import-Path: github.com/mikefarah/yq
XSBC-Original-Maintainer: Roberto Mier Escandón <rmescandon@gmail.com>
Package: yq
Architecture: any
Built-Using: ${misc:Built-Using}
Depends: ${shlibs:Depends},
${misc:Depends}
Description:
a lightweight and portable command-line YAML processor
Depends: ${shlibs:Depends}, ${misc:Depends}
Description: a lightweight and portable command-line YAML processor
.
The aim of the project is to be the [jq](https://github.com/stedolan/jq) or sed of yaml files.
The aim of the project is to be the
[jq](https://github.com/stedolan/jq) or sed of yaml files.

24
debian/rules vendored
View File

@@ -14,46 +14,46 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
PROJECT := yq
OWNER := mikefarah
REPO := github.com
GOVERSION := 1.10
GOVERSION := 1.13
export DH_OPTIONS
export DH_GOPKG := ${REPO}/${OWNER}/${PROJECT}
export GOROOT := /usr/lib/go-${GOVERSION}
export GOPATH := ${CURDIR}/_build
export GOBIN := ${GOPATH}/bin
export PATH := ${GOROOT}/bin:${GOBIN}:${PATH}
BLDPATH := $(shell dpkg-architecture -qDEB_BUILD_GNU_TYPE)
SRCDIR := ${CURDIR}/_build/src/${DH_GOPKG}
export GOCACHE := /tmp/gocache
export GOFLAGS := -mod=vendor
SRCDIR := ${GOPATH}/src/${DH_GOPKG}
DESTDIR := ${CURDIR}/debian/${PROJECT}
BINDIR := /usr/bin
ASSETSDIR := /usr/share/${PROJECT}
%:
dh $@ --buildsystem=golang --with=golang
dh $@ --builddirectory=${GOPATH} --buildsystem=golang
override_dh_auto_build:
mkdir -p ${SRCDIR}
mkdir -p ${GOBIN}
# copy project to local srcdir to build from there
rsync -avz --progress --exclude=obj-${BLDPATH} --exclude=debian . $(SRCDIR)
rsync -avz --progress --exclude=_build --exclude=debian --exclude=tmp. --exclude=go.mod . $(SRCDIR)
# build go code
(cd ${SRCDIR} && go install ./...)
(cd ${SRCDIR} && go install -buildmode=pie ./...)
override_dh_auto_test:
(cd ${SRCDIR} && go test -v ./...)
override_dh_auto_install:
mkdir -p ${DESTDIR}/${BINDIR}
mkdir -p ${DESTDIR}/${ASSETSDIR}
cp ${CURDIR}/_build/bin/yq ${DESTDIR}/${BINDIR}
cp -rf ${SRCDIR}/LICENSE ${DESTDIR}/${ASSETSDIR}
cp -rf ${SRCDIR}/README.md ${DESTDIR}/${PLUGINSDIR}
cp ${GOBIN}/yq ${DESTDIR}/${BINDIR}
cp -f ${SRCDIR}/LICENSE ${DESTDIR}/${ASSETSDIR}
chmod a+x ${DESTDIR}/${BINDIR}/yq
override_dh_auto_clean:
dh_clean
rm -rf ${CURDIR}/obj-${BLDPATH}
rm -rf ${CURDIR}/_build

View File

@@ -32,7 +32,7 @@
<meta name="lang:search.tokenizer" content="[\s\-]+">
<link rel="shortcut icon" href="/assets/images/favicon.png">
<meta name="generator" content="mkdocs-1.0.4, mkdocs-material-4.2.0">
<meta name="generator" content="mkdocs-1.0.4, mkdocs-material-4.6.0">
@@ -40,17 +40,17 @@
<link rel="stylesheet" href="/assets/stylesheets/application.750b69bd.css">
<link rel="stylesheet" href="/assets/stylesheets/application.1b62728e.css">
<script src="/assets/javascripts/modernizr.74668098.js"></script>
<script src="/assets/javascripts/modernizr.268332fc.js"></script>
<link href="https://fonts.gstatic.com" rel="preconnect" crossorigin>
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:300,400,400i,700|Roboto+Mono">
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:300,400,400i,700%7CRoboto+Mono&display=fallback">
<style>body,input{font-family:"Roboto","Helvetica Neue",Helvetica,Arial,sans-serif}code,kbd,pre{font-family:"Roboto Mono","Courier New",Courier,monospace}</style>
@@ -69,24 +69,7 @@
<defs>
<svg xmlns="http://www.w3.org/2000/svg" width="416" height="448"
viewBox="0 0 416 448" id="__github">
<path fill="currentColor" d="M160 304q0 10-3.125 20.5t-10.75 19-18.125
8.5-18.125-8.5-10.75-19-3.125-20.5 3.125-20.5 10.75-19 18.125-8.5
18.125 8.5 10.75 19 3.125 20.5zM320 304q0 10-3.125 20.5t-10.75
19-18.125 8.5-18.125-8.5-10.75-19-3.125-20.5 3.125-20.5 10.75-19
18.125-8.5 18.125 8.5 10.75 19 3.125 20.5zM360
304q0-30-17.25-51t-46.75-21q-10.25 0-48.75 5.25-17.75 2.75-39.25
2.75t-39.25-2.75q-38-5.25-48.75-5.25-29.5 0-46.75 21t-17.25 51q0 22 8
38.375t20.25 25.75 30.5 15 35 7.375 37.25 1.75h42q20.5 0
37.25-1.75t35-7.375 30.5-15 20.25-25.75 8-38.375zM416 260q0 51.75-15.25
82.75-9.5 19.25-26.375 33.25t-35.25 21.5-42.5 11.875-42.875 5.5-41.75
1.125q-19.5 0-35.5-0.75t-36.875-3.125-38.125-7.5-34.25-12.875-30.25-20.25-21.5-28.75q-15.5-30.75-15.5-82.75
0-59.25 34-99-6.75-20.5-6.75-42.5 0-29 12.75-54.5 27 0 47.5 9.875t47.25
30.875q36.75-8.75 77.25-8.75 37 0 70 8 26.25-20.5
46.75-30.25t47.25-9.75q12.75 25.5 12.75 54.5 0 21.75-6.75 42 34 40 34
99.5z" />
</svg>
<svg xmlns="http://www.w3.org/2000/svg" width="416" height="448" viewBox="0 0 416 448" id="__github"><path fill="currentColor" d="M160 304q0 10-3.125 20.5t-10.75 19T128 352t-18.125-8.5-10.75-19T96 304t3.125-20.5 10.75-19T128 256t18.125 8.5 10.75 19T160 304zm160 0q0 10-3.125 20.5t-10.75 19T288 352t-18.125-8.5-10.75-19T256 304t3.125-20.5 10.75-19T288 256t18.125 8.5 10.75 19T320 304zm40 0q0-30-17.25-51T296 232q-10.25 0-48.75 5.25Q229.5 240 208 240t-39.25-2.75Q130.75 232 120 232q-29.5 0-46.75 21T56 304q0 22 8 38.375t20.25 25.75 30.5 15 35 7.375 37.25 1.75h42q20.5 0 37.25-1.75t35-7.375 30.5-15 20.25-25.75T360 304zm56-44q0 51.75-15.25 82.75-9.5 19.25-26.375 33.25t-35.25 21.5-42.5 11.875-42.875 5.5T212 416q-19.5 0-35.5-.75t-36.875-3.125-38.125-7.5-34.25-12.875T37 371.5t-21.5-28.75Q0 312 0 260q0-59.25 34-99-6.75-20.5-6.75-42.5 0-29 12.75-54.5 27 0 47.5 9.875t47.25 30.875Q171.5 96 212 96q37 0 70 8 26.25-20.5 46.75-30.25T376 64q12.75 25.5 12.75 54.5 0 21.75-6.75 42 34 40 34 99.5z"/></svg>
</defs>
</svg>
@@ -116,6 +99,8 @@
</span>
<span class="md-header-nav__topic">
</span>
</div>
@@ -180,7 +165,7 @@
<main class="md-main">
<main class="md-main" role="main">
<div class="md-main__inner md-grid" data-md-component="container">
@@ -225,104 +210,8 @@
<li class="md-nav__item">
<a href="/." title="Install" class="md-nav__link">
Install
</a>
</li>
<li class="md-nav__item">
<a href="/read/" title="Read" class="md-nav__link">
Read
</a>
</li>
<li class="md-nav__item">
<a href="/path_expressions/" title="Path Expressions" class="md-nav__link">
Path Expressions
</a>
</li>
<li class="md-nav__item">
<a href="/write/" title="Write/Update" class="md-nav__link">
Write/Update
</a>
</li>
<li class="md-nav__item">
<a href="/prefix/" title="Prefix" class="md-nav__link">
Prefix
</a>
</li>
<li class="md-nav__item">
<a href="/delete/" title="Delete" class="md-nav__link">
Delete
</a>
</li>
<li class="md-nav__item">
<a href="/create/" title="Create" class="md-nav__link">
Create
</a>
</li>
<li class="md-nav__item">
<a href="/convert/" title="Convert" class="md-nav__link">
Convert
</a>
</li>
<li class="md-nav__item">
<a href="/merge/" title="Merge" class="md-nav__link">
Merge
<a href="/." title="Home" class="md-nav__link">
Home
</a>
</li>
@@ -364,22 +253,13 @@
Material for MkDocs</a>
</div>
<div class="md-footer-social">
<link rel="stylesheet" href="/assets/fonts/font-awesome.css">
<a href="https://github.com/mikefarah" class="md-footer-social__link fa fa-github"></a>
<a href="https://www.linkedin.com/in/mike-farah-b5a75b2/" class="md-footer-social__link fa fa-linkedin"></a>
</div>
</div>
</div>
</footer>
</div>
<script src="/assets/javascripts/application.39abc4af.js"></script>
<script src="/assets/javascripts/application.808e90bb.js"></script>
<script>app.initialize({version:"1.0.4",url:{base:"/"}})</script>

View File

@@ -1,20 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="352" height="448"
viewBox="0 0 352 448" id="__bitbucket">
<path fill="currentColor" d="M203.75 214.75q2 15.75-12.625 25.25t-27.875
1.5q-9.75-4.25-13.375-14.5t-0.125-20.5 13-14.5q9-4.5 18.125-3t16 8.875
6.875 16.875zM231.5 209.5q-3.5-26.75-28.25-41t-49.25-3.25q-15.75
7-25.125 22.125t-8.625 32.375q1 22.75 19.375 38.75t41.375 14q22.75-2
38-21t12.5-42zM291.25
74q-5-6.75-14-11.125t-14.5-5.5-17.75-3.125q-72.75-11.75-141.5 0.5-10.75
1.75-16.5 3t-13.75 5.5-12.5 10.75q7.5 7 19 11.375t18.375 5.5 21.875
2.875q57 7.25 112 0.25 15.75-2 22.375-3t18.125-5.375 18.75-11.625zM305.5
332.75q-2 6.5-3.875 19.125t-3.5 21-7.125 17.5-14.5 14.125q-21.5
12-47.375 17.875t-50.5 5.5-50.375-4.625q-11.5-2-20.375-4.5t-19.125-6.75-18.25-10.875-13-15.375q-6.25-24-14.25-73l1.5-4
4.5-2.25q55.75 37 126.625 37t126.875-37q5.25 1.5 6 5.75t-1.25 11.25-2
9.25zM350.75 92.5q-6.5 41.75-27.75 163.75-1.25 7.5-6.75 14t-10.875
10-13.625 7.75q-63 31.5-152.5
22-62-6.75-98.5-34.75-3.75-3-6.375-6.625t-4.25-8.75-2.25-8.5-1.5-9.875-1.375-8.75q-2.25-12.5-6.625-37.5t-7-40.375-5.875-36.875-5.5-39.5q0.75-6.5
4.375-12.125t7.875-9.375 11.25-7.5 11.5-5.625 12-4.625q31.25-11.5
78.25-16 94.75-9.25 169 12.5 38.75 11.5 53.75 30.5 4 5 4.125
12.75t-1.375 13.5z" />
</svg>
<svg xmlns="http://www.w3.org/2000/svg" width="352" height="448" viewBox="0 0 352 448" id="__bitbucket"><path fill="currentColor" d="M203.75 214.75q2 15.75-12.625 25.25t-27.875 1.5q-9.75-4.25-13.375-14.5t-.125-20.5 13-14.5q9-4.5 18.125-3t16 8.875 6.875 16.875zm27.75-5.25q-3.5-26.75-28.25-41T154 165.25q-15.75 7-25.125 22.125t-8.625 32.375q1 22.75 19.375 38.75t41.375 14q22.75-2 38-21t12.5-42zM291.25 74q-5-6.75-14-11.125t-14.5-5.5T245 54.25q-72.75-11.75-141.5.5-10.75 1.75-16.5 3t-13.75 5.5T60.75 74q7.5 7 19 11.375t18.375 5.5T120 93.75Q177 101 232 94q15.75-2 22.375-3t18.125-5.375T291.25 74zm14.25 258.75q-2 6.5-3.875 19.125t-3.5 21-7.125 17.5-14.5 14.125q-21.5 12-47.375 17.875t-50.5 5.5-50.375-4.625q-11.5-2-20.375-4.5T88.75 412 70.5 401.125t-13-15.375q-6.25-24-14.25-73l1.5-4 4.5-2.25q55.75 37 126.625 37t126.875-37q5.25 1.5 6 5.75t-1.25 11.25-2 9.25zM350.75 92.5q-6.5 41.75-27.75 163.75-1.25 7.5-6.75 14t-10.875 10T291.75 288q-63 31.5-152.5 22-62-6.75-98.5-34.75-3.75-3-6.375-6.625t-4.25-8.75-2.25-8.5-1.5-9.875T25 232.75q-2.25-12.5-6.625-37.5t-7-40.375T5.5 118 0 78.5Q.75 72 4.375 66.375T12.25 57t11.25-7.5T35 43.875t12-4.625q31.25-11.5 78.25-16 94.75-9.25 169 12.5Q333 47.25 348 66.25q4 5 4.125 12.75t-1.375 13.5z"/></svg>

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@@ -1,18 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="416" height="448"
viewBox="0 0 416 448" id="__github">
<path fill="currentColor" d="M160 304q0 10-3.125 20.5t-10.75 19-18.125
8.5-18.125-8.5-10.75-19-3.125-20.5 3.125-20.5 10.75-19 18.125-8.5
18.125 8.5 10.75 19 3.125 20.5zM320 304q0 10-3.125 20.5t-10.75
19-18.125 8.5-18.125-8.5-10.75-19-3.125-20.5 3.125-20.5 10.75-19
18.125-8.5 18.125 8.5 10.75 19 3.125 20.5zM360
304q0-30-17.25-51t-46.75-21q-10.25 0-48.75 5.25-17.75 2.75-39.25
2.75t-39.25-2.75q-38-5.25-48.75-5.25-29.5 0-46.75 21t-17.25 51q0 22 8
38.375t20.25 25.75 30.5 15 35 7.375 37.25 1.75h42q20.5 0
37.25-1.75t35-7.375 30.5-15 20.25-25.75 8-38.375zM416 260q0 51.75-15.25
82.75-9.5 19.25-26.375 33.25t-35.25 21.5-42.5 11.875-42.875 5.5-41.75
1.125q-19.5 0-35.5-0.75t-36.875-3.125-38.125-7.5-34.25-12.875-30.25-20.25-21.5-28.75q-15.5-30.75-15.5-82.75
0-59.25 34-99-6.75-20.5-6.75-42.5 0-29 12.75-54.5 27 0 47.5 9.875t47.25
30.875q36.75-8.75 77.25-8.75 37 0 70 8 26.25-20.5
46.75-30.25t47.25-9.75q12.75 25.5 12.75 54.5 0 21.75-6.75 42 34 40 34
99.5z" />
</svg>
<svg xmlns="http://www.w3.org/2000/svg" width="416" height="448" viewBox="0 0 416 448" id="__github"><path fill="currentColor" d="M160 304q0 10-3.125 20.5t-10.75 19T128 352t-18.125-8.5-10.75-19T96 304t3.125-20.5 10.75-19T128 256t18.125 8.5 10.75 19T160 304zm160 0q0 10-3.125 20.5t-10.75 19T288 352t-18.125-8.5-10.75-19T256 304t3.125-20.5 10.75-19T288 256t18.125 8.5 10.75 19T320 304zm40 0q0-30-17.25-51T296 232q-10.25 0-48.75 5.25Q229.5 240 208 240t-39.25-2.75Q130.75 232 120 232q-29.5 0-46.75 21T56 304q0 22 8 38.375t20.25 25.75 30.5 15 35 7.375 37.25 1.75h42q20.5 0 37.25-1.75t35-7.375 30.5-15 20.25-25.75T360 304zm56-44q0 51.75-15.25 82.75-9.5 19.25-26.375 33.25t-35.25 21.5-42.5 11.875-42.875 5.5T212 416q-19.5 0-35.5-.75t-36.875-3.125-38.125-7.5-34.25-12.875T37 371.5t-21.5-28.75Q0 312 0 260q0-59.25 34-99-6.75-20.5-6.75-42.5 0-29 12.75-54.5 27 0 47.5 9.875t47.25 30.875Q171.5 96 212 96q37 0 70 8 26.25-20.5 46.75-30.25T376 64q12.75 25.5 12.75 54.5 0 21.75-6.75 42 34 40 34 99.5z"/></svg>

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 993 B

View File

@@ -1,38 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="500" height="500"
viewBox="0 0 500 500" id="__gitlab">
<g transform="translate(156.197863, 1.160267)">
<path fill="currentColor"
d="M93.667,473.347L93.667,473.347l90.684-279.097H2.983L93.667,
473.347L93.667,473.347z" />
</g>
<g transform="translate(28.531199, 1.160800)" opacity="0.7">
<path fill="currentColor"
d="M221.333,473.345L130.649,194.25H3.557L221.333,473.345L221.333,
473.345z" />
</g>
<g transform="translate(0.088533, 0.255867)" opacity="0.5">
<path fill="currentColor"
d="M32,195.155L32,195.155L4.441,279.97c-2.513,7.735,0.24,16.21,6.821,
20.99l238.514,173.29 L32,195.155L32,195.155z" />
</g>
<g transform="translate(29.421866, 280.255593)">
<path fill="currentColor"
d="M2.667-84.844h127.092L75.14-252.942c-2.811-8.649-15.047-8.649-17.856,
0L2.667-84.844 L2.667-84.844z" />
</g>
<g transform="translate(247.197860, 1.160800)" opacity="0.7">
<path fill="currentColor"
d="M2.667,473.345L93.351,194.25h127.092L2.667,473.345L2.667,
473.345z" />
</g>
<g transform="translate(246.307061, 0.255867)" opacity="0.5">
<path fill="currentColor"
d="M221.334,195.155L221.334,195.155l27.559,84.815c2.514,7.735-0.24,
16.21-6.821,20.99 L3.557,474.25L221.334,195.155L221.334,195.155z" />
</g>
<g transform="translate(336.973725, 280.255593)">
<path fill="currentColor"
d="M130.667-84.844H3.575l54.618-168.098c2.811-8.649,15.047-8.649,
17.856,0L130.667-84.844 L130.667-84.844z" />
</g>
</svg>
<svg xmlns="http://www.w3.org/2000/svg" width="500" height="500" viewBox="0 0 500 500" id="__gitlab"><path fill="currentColor" d="M93.667 473.347l90.684-279.097H2.983l90.684 279.097z" transform="translate(156.198 1.16)"/><path fill="currentColor" d="M221.333 473.345L130.649 194.25H3.557l217.776 279.095z" transform="translate(28.531 1.16)" opacity=".7"/><path fill="currentColor" d="M32 195.155L4.441 279.97a18.773 18.773 0 0 0 6.821 20.99l238.514 173.29L32 195.155z" transform="translate(.089 .256)" opacity=".5"/><path fill="currentColor" d="M2.667-84.844h127.092L75.14-252.942c-2.811-8.649-15.047-8.649-17.856 0L2.667-84.844z" transform="translate(29.422 280.256)"/><path fill="currentColor" d="M2.667 473.345L93.351 194.25h127.092L2.667 473.345z" transform="translate(247.198 1.16)" opacity=".7"/><path fill="currentColor" d="M221.334 195.155l27.559 84.815a18.772 18.772 0 0 1-6.821 20.99L3.557 474.25l217.777-279.095z" transform="translate(246.307 .256)" opacity=".5"/><path fill="currentColor" d="M130.667-84.844H3.575l54.618-168.098c2.811-8.649 15.047-8.649 17.856 0l54.618 168.098z" transform="translate(336.974 280.256)"/></svg>

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -1 +1,17 @@
/*!
* Lunr languages, `Danish` language
* https://github.com/MihaiValentin/lunr-languages
*
* Copyright 2014, Mihai Valentin
* http://www.mozilla.org/MPL/
*/
/*!
* based on
* Snowball JavaScript Library v0.3
* http://code.google.com/p/urim/
* http://snowball.tartarus.org/
*
* Copyright 2010, Oleg Mazko
* http://www.mozilla.org/MPL/
*/
!function(e,r){"function"==typeof define&&define.amd?define(r):"object"==typeof exports?module.exports=r():r()(e.lunr)}(this,function(){return function(e){if(void 0===e)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===e.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");var r,m,i;e.da=function(){this.pipeline.reset(),this.pipeline.add(e.da.trimmer,e.da.stopWordFilter,e.da.stemmer),this.searchPipeline&&(this.searchPipeline.reset(),this.searchPipeline.add(e.da.stemmer))},e.da.wordCharacters="A-Za-zªºÀ-ÖØ-öø-ʸˠ-ˤᴀ-ᴥᴬ-ᵜᵢ-ᵥᵫ-ᵷᵹ-ᶾḀ-ỿⁱⁿₐ-ₜKÅℲⅎⅠ-ↈⱠ-ⱿꜢ-ꞇꞋ-ꞭꞰ-ꞷꟷ-ꟿꬰ-ꭚꭜ-ꭤff-stA--",e.da.trimmer=e.trimmerSupport.generateTrimmer(e.da.wordCharacters),e.Pipeline.registerFunction(e.da.trimmer,"trimmer-da"),e.da.stemmer=(r=e.stemmerSupport.Among,m=e.stemmerSupport.SnowballProgram,i=new function(){var i,t,n,s=[new r("hed",-1,1),new r("ethed",0,1),new r("ered",-1,1),new r("e",-1,1),new r("erede",3,1),new r("ende",3,1),new r("erende",5,1),new r("ene",3,1),new r("erne",3,1),new r("ere",3,1),new r("en",-1,1),new r("heden",10,1),new r("eren",10,1),new r("er",-1,1),new r("heder",13,1),new r("erer",13,1),new r("s",-1,2),new r("heds",16,1),new r("es",16,1),new r("endes",18,1),new r("erendes",19,1),new r("enes",18,1),new r("ernes",18,1),new r("eres",18,1),new r("ens",16,1),new r("hedens",24,1),new r("erens",24,1),new r("ers",16,1),new r("ets",16,1),new r("erets",28,1),new r("et",-1,1),new r("eret",30,1)],o=[new r("gd",-1,-1),new r("dt",-1,-1),new r("gt",-1,-1),new r("kt",-1,-1)],a=[new r("ig",-1,1),new r("lig",0,1),new r("elig",1,1),new r("els",-1,1),new r("løst",-1,2)],d=[17,65,16,1,0,0,0,0,0,0,0,0,0,0,0,0,48,0,128],u=[239,254,42,3,0,0,0,0,0,0,0,0,0,0,0,0,16],c=new m;function l(){var e,r=c.limit-c.cursor;c.cursor>=t&&(e=c.limit_backward,c.limit_backward=t,c.ket=c.cursor,c.find_among_b(o,4)?(c.bra=c.cursor,c.limit_backward=e,c.cursor=c.limit-r,c.cursor>c.limit_backward&&(c.cursor--,c.bra=c.cursor,c.slice_del())):c.limit_backward=e)}this.setCurrent=function(e){c.setCurrent(e)},this.getCurrent=function(){return c.getCurrent()},this.stem=function(){var e,r=c.cursor;return function(){var e,r=c.cursor+3;if(t=c.limit,0<=r&&r<=c.limit){for(i=r;;){if(e=c.cursor,c.in_grouping(d,97,248)){c.cursor=e;break}if((c.cursor=e)>=c.limit)return;c.cursor++}for(;!c.out_grouping(d,97,248);){if(c.cursor>=c.limit)return;c.cursor++}(t=c.cursor)<i&&(t=i)}}(),c.limit_backward=r,c.cursor=c.limit,function(){var e,r;if(c.cursor>=t&&(r=c.limit_backward,c.limit_backward=t,c.ket=c.cursor,e=c.find_among_b(s,32),c.limit_backward=r,e))switch(c.bra=c.cursor,e){case 1:c.slice_del();break;case 2:c.in_grouping_b(u,97,229)&&c.slice_del()}}(),c.cursor=c.limit,l(),c.cursor=c.limit,function(){var e,r,i,n=c.limit-c.cursor;if(c.ket=c.cursor,c.eq_s_b(2,"st")&&(c.bra=c.cursor,c.eq_s_b(2,"ig")&&c.slice_del()),c.cursor=c.limit-n,c.cursor>=t&&(r=c.limit_backward,c.limit_backward=t,c.ket=c.cursor,e=c.find_among_b(a,5),c.limit_backward=r,e))switch(c.bra=c.cursor,e){case 1:c.slice_del(),i=c.limit-c.cursor,l(),c.cursor=c.limit-i;break;case 2:c.slice_from("løs")}}(),c.cursor=c.limit,c.cursor>=t&&(e=c.limit_backward,c.limit_backward=t,c.ket=c.cursor,c.out_grouping_b(d,97,248)?(c.bra=c.cursor,n=c.slice_to(n),c.limit_backward=e,c.eq_v_b(n)&&c.slice_del()):c.limit_backward=e),!0}},function(e){return"function"==typeof e.update?e.update(function(e){return i.setCurrent(e),i.stem(),i.getCurrent()}):(i.setCurrent(e),i.stem(),i.getCurrent())}),e.Pipeline.registerFunction(e.da.stemmer,"stemmer-da"),e.da.stopWordFilter=e.generateStopWordFilter("ad af alle alt anden at blev blive bliver da de dem den denne der deres det dette dig din disse dog du efter eller en end er et for fra ham han hans har havde have hende hendes her hos hun hvad hvis hvor i ikke ind jeg jer jo kunne man mange med meget men mig min mine mit mod ned noget nogle nu når og også om op os over på selv sig sin sine sit skal skulle som sådan thi til ud under var vi vil ville vor være været".split(" ")),e.Pipeline.registerFunction(e.da.stopWordFilter,"stopWordFilter-da")}});

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -1 +1,17 @@
/*!
* Lunr languages, `Japanese` language
* https://github.com/MihaiValentin/lunr-languages
*
* Copyright 2014, Chad Liu
* http://www.mozilla.org/MPL/
*/
/*!
* based on
* Snowball JavaScript Library v0.3
* http://code.google.com/p/urim/
* http://snowball.tartarus.org/
*
* Copyright 2010, Oleg Mazko
* http://www.mozilla.org/MPL/
*/
!function(e,r){"function"==typeof define&&define.amd?define(r):"object"==typeof exports?module.exports=r():r()(e.lunr)}(this,function(){return function(m){if(void 0===m)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===m.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");var l="2"==m.version[0];m.ja=function(){this.pipeline.reset(),this.pipeline.add(m.ja.trimmer,m.ja.stopWordFilter,m.ja.stemmer),l?this.tokenizer=m.ja.tokenizer:(m.tokenizer&&(m.tokenizer=m.ja.tokenizer),this.tokenizerFn&&(this.tokenizerFn=m.ja.tokenizer))};var j=new m.TinySegmenter;m.ja.tokenizer=function(e){var r,t,i,n,o,s,p,a,u;if(!arguments.length||null==e||null==e)return[];if(Array.isArray(e))return e.map(function(e){return l?new m.Token(e.toLowerCase()):e.toLowerCase()});for(r=(t=e.toString().toLowerCase().replace(/^\s+/,"")).length-1;0<=r;r--)if(/\S/.test(t.charAt(r))){t=t.substring(0,r+1);break}for(o=[],i=t.length,p=a=0;a<=i;a++)if(s=a-p,t.charAt(a).match(/\s/)||a==i){if(0<s)for(n=j.segment(t.slice(p,a)).filter(function(e){return!!e}),u=p,r=0;r<n.length;r++)l?o.push(new m.Token(n[r],{position:[u,n[r].length],index:o.length})):o.push(n[r]),u+=n[r].length;p=a+1}return o},m.ja.stemmer=function(e){return e},m.Pipeline.registerFunction(m.ja.stemmer,"stemmer-ja"),m.ja.wordCharacters="一二三四五六七八九十百千万億兆一-龠々〆ヵヶぁ-んァ-ヴーア-ン゙a-zA-Z--0-9-",m.ja.trimmer=m.trimmerSupport.generateTrimmer(m.ja.wordCharacters),m.Pipeline.registerFunction(m.ja.trimmer,"trimmer-ja"),m.ja.stopWordFilter=m.generateStopWordFilter("これ それ あれ この その あの ここ そこ あそこ こちら どこ だれ なに なん 何 私 貴方 貴方方 我々 私達 あの人 あのかた 彼女 彼 です あります おります います は が の に を で え から まで より も どの と し それで しかし".split(" ")),m.Pipeline.registerFunction(m.ja.stopWordFilter,"stopWordFilter-ja"),m.jp=m.ja,m.Pipeline.registerFunction(m.jp.stemmer,"stemmer-jp"),m.Pipeline.registerFunction(m.jp.trimmer,"trimmer-jp"),m.Pipeline.registerFunction(m.jp.stopWordFilter,"stopWordFilter-jp")}});

View File

@@ -1 +1 @@
!function(e,i){"function"==typeof define&&define.amd?define(i):"object"==typeof exports?module.exports=i():i()(e.lunr)}(this,function(){return function(o){o.multiLanguage=function(){for(var e=Array.prototype.slice.call(arguments),i=e.join("-"),t="",r=[],n=[],s=0;s<e.length;++s)"en"==e[s]?(t+="\\w",r.unshift(o.stopWordFilter),r.push(o.stemmer),n.push(o.stemmer)):(t+=o[e[s]].wordCharacters,r.unshift(o[e[s]].stopWordFilter),r.push(o[e[s]].stemmer),n.push(o[e[s]].stemmer));var p=o.trimmerSupport.generateTrimmer(t);return o.Pipeline.registerFunction(p,"lunr-multi-trimmer-"+i),r.unshift(p),function(){this.pipeline.reset(),this.pipeline.add.apply(this.pipeline,r),this.searchPipeline&&(this.searchPipeline.reset(),this.searchPipeline.add.apply(this.searchPipeline,n))}}}});
!function(e,t){"function"==typeof define&&define.amd?define(t):"object"==typeof exports?module.exports=t():t()(e.lunr)}(this,function(){return function(o){o.multiLanguage=function(){for(var e=Array.prototype.slice.call(arguments),t=e.join("-"),i="",r=[],n=[],s=0;s<e.length;++s)"en"==e[s]?(i+="\\w",r.unshift(o.stopWordFilter),r.push(o.stemmer),n.push(o.stemmer)):(i+=o[e[s]].wordCharacters,o[e[s]].stopWordFilter&&r.unshift(o[e[s]].stopWordFilter),o[e[s]].stemmer&&(r.push(o[e[s]].stemmer),n.push(o[e[s]].stemmer)));var p=o.trimmerSupport.generateTrimmer(i);return o.Pipeline.registerFunction(p,"lunr-multi-trimmer-"+t),r.unshift(p),function(){this.pipeline.reset(),this.pipeline.add.apply(this.pipeline,r),this.searchPipeline&&(this.searchPipeline.reset(),this.searchPipeline.add.apply(this.searchPipeline,n))}}}});

File diff suppressed because one or more lines are too long

View File

@@ -1 +1,17 @@
/*!
* Lunr languages, `Norwegian` language
* https://github.com/MihaiValentin/lunr-languages
*
* Copyright 2014, Mihai Valentin
* http://www.mozilla.org/MPL/
*/
/*!
* based on
* Snowball JavaScript Library v0.3
* http://code.google.com/p/urim/
* http://snowball.tartarus.org/
*
* Copyright 2010, Oleg Mazko
* http://www.mozilla.org/MPL/
*/
!function(e,r){"function"==typeof define&&define.amd?define(r):"object"==typeof exports?module.exports=r():r()(e.lunr)}(this,function(){return function(e){if(void 0===e)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===e.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");var r,n,i;e.no=function(){this.pipeline.reset(),this.pipeline.add(e.no.trimmer,e.no.stopWordFilter,e.no.stemmer),this.searchPipeline&&(this.searchPipeline.reset(),this.searchPipeline.add(e.no.stemmer))},e.no.wordCharacters="A-Za-zªºÀ-ÖØ-öø-ʸˠ-ˤᴀ-ᴥᴬ-ᵜᵢ-ᵥᵫ-ᵷᵹ-ᶾḀ-ỿⁱⁿₐ-ₜKÅℲⅎⅠ-ↈⱠ-ⱿꜢ-ꞇꞋ-ꞭꞰ-ꞷꟷ-ꟿꬰ-ꭚꭜ-ꭤff-stA--",e.no.trimmer=e.trimmerSupport.generateTrimmer(e.no.wordCharacters),e.Pipeline.registerFunction(e.no.trimmer,"trimmer-no"),e.no.stemmer=(r=e.stemmerSupport.Among,n=e.stemmerSupport.SnowballProgram,i=new function(){var o,s,a=[new r("a",-1,1),new r("e",-1,1),new r("ede",1,1),new r("ande",1,1),new r("ende",1,1),new r("ane",1,1),new r("ene",1,1),new r("hetene",6,1),new r("erte",1,3),new r("en",-1,1),new r("heten",9,1),new r("ar",-1,1),new r("er",-1,1),new r("heter",12,1),new r("s",-1,2),new r("as",14,1),new r("es",14,1),new r("edes",16,1),new r("endes",16,1),new r("enes",16,1),new r("hetenes",19,1),new r("ens",14,1),new r("hetens",21,1),new r("ers",14,1),new r("ets",14,1),new r("et",-1,1),new r("het",25,1),new r("ert",-1,3),new r("ast",-1,1)],m=[new r("dt",-1,-1),new r("vt",-1,-1)],l=[new r("leg",-1,1),new r("eleg",0,1),new r("ig",-1,1),new r("eig",2,1),new r("lig",2,1),new r("elig",4,1),new r("els",-1,1),new r("lov",-1,1),new r("elov",7,1),new r("slov",7,1),new r("hetslov",9,1)],u=[17,65,16,1,0,0,0,0,0,0,0,0,0,0,0,0,48,0,128],d=[119,125,149,1],c=new n;this.setCurrent=function(e){c.setCurrent(e)},this.getCurrent=function(){return c.getCurrent()},this.stem=function(){var e,r,n,i,t=c.cursor;return function(){var e,r=c.cursor+3;if(s=c.limit,0<=r||r<=c.limit){for(o=r;;){if(e=c.cursor,c.in_grouping(u,97,248)){c.cursor=e;break}if(e>=c.limit)return;c.cursor=e+1}for(;!c.out_grouping(u,97,248);){if(c.cursor>=c.limit)return;c.cursor++}(s=c.cursor)<o&&(s=o)}}(),c.limit_backward=t,c.cursor=c.limit,function(){var e,r,n;if(c.cursor>=s&&(r=c.limit_backward,c.limit_backward=s,c.ket=c.cursor,e=c.find_among_b(a,29),c.limit_backward=r,e))switch(c.bra=c.cursor,e){case 1:c.slice_del();break;case 2:n=c.limit-c.cursor,c.in_grouping_b(d,98,122)?c.slice_del():(c.cursor=c.limit-n,c.eq_s_b(1,"k")&&c.out_grouping_b(u,97,248)&&c.slice_del());break;case 3:c.slice_from("er")}}(),c.cursor=c.limit,r=c.limit-c.cursor,c.cursor>=s&&(e=c.limit_backward,c.limit_backward=s,c.ket=c.cursor,c.find_among_b(m,2)?(c.bra=c.cursor,c.limit_backward=e,c.cursor=c.limit-r,c.cursor>c.limit_backward&&(c.cursor--,c.bra=c.cursor,c.slice_del())):c.limit_backward=e),c.cursor=c.limit,c.cursor>=s&&(i=c.limit_backward,c.limit_backward=s,c.ket=c.cursor,(n=c.find_among_b(l,11))?(c.bra=c.cursor,c.limit_backward=i,1==n&&c.slice_del()):c.limit_backward=i),!0}},function(e){return"function"==typeof e.update?e.update(function(e){return i.setCurrent(e),i.stem(),i.getCurrent()}):(i.setCurrent(e),i.stem(),i.getCurrent())}),e.Pipeline.registerFunction(e.no.stemmer,"stemmer-no"),e.no.stopWordFilter=e.generateStopWordFilter("alle at av bare begge ble blei bli blir blitt både båe da de deg dei deim deira deires dem den denne der dere deres det dette di din disse ditt du dykk dykkar då eg ein eit eitt eller elles en enn er et ett etter for fordi fra før ha hadde han hans har hennar henne hennes her hjå ho hoe honom hoss hossen hun hva hvem hver hvilke hvilken hvis hvor hvordan hvorfor i ikke ikkje ikkje ingen ingi inkje inn inni ja jeg kan kom korleis korso kun kunne kva kvar kvarhelst kven kvi kvifor man mange me med medan meg meget mellom men mi min mine mitt mot mykje ned no noe noen noka noko nokon nokor nokre nå når og også om opp oss over på samme seg selv si si sia sidan siden sin sine sitt sjøl skal skulle slik so som som somme somt så sånn til um upp ut uten var vart varte ved vere verte vi vil ville vore vors vort vår være være vært å".split(" ")),e.Pipeline.registerFunction(e.no.stopWordFilter,"stopWordFilter-no")}});

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -1 +1,9 @@
/*!
* Snowball JavaScript Library v0.3
* http://code.google.com/p/urim/
* http://snowball.tartarus.org/
*
* Copyright 2010, Oleg Mazko
* http://www.mozilla.org/MPL/
*/
!function(r,t){"function"==typeof define&&define.amd?define(t):"object"==typeof exports?module.exports=t():t()(r.lunr)}(this,function(){return function(r){r.stemmerSupport={Among:function(r,t,i,s){if(this.toCharArray=function(r){for(var t=r.length,i=new Array(t),s=0;s<t;s++)i[s]=r.charCodeAt(s);return i},!r&&""!=r||!t&&0!=t||!i)throw"Bad Among initialisation: s:"+r+", substring_i: "+t+", result: "+i;this.s_size=r.length,this.s=this.toCharArray(r),this.substring_i=t,this.result=i,this.method=s},SnowballProgram:function(){var b;return{bra:0,ket:0,limit:0,cursor:0,limit_backward:0,setCurrent:function(r){b=r,this.cursor=0,this.limit=r.length,this.limit_backward=0,this.bra=this.cursor,this.ket=this.limit},getCurrent:function(){var r=b;return b=null,r},in_grouping:function(r,t,i){if(this.cursor<this.limit){var s=b.charCodeAt(this.cursor);if(s<=i&&t<=s&&r[(s-=t)>>3]&1<<(7&s))return this.cursor++,!0}return!1},in_grouping_b:function(r,t,i){if(this.cursor>this.limit_backward){var s=b.charCodeAt(this.cursor-1);if(s<=i&&t<=s&&r[(s-=t)>>3]&1<<(7&s))return this.cursor--,!0}return!1},out_grouping:function(r,t,i){if(this.cursor<this.limit){var s=b.charCodeAt(this.cursor);if(i<s||s<t)return this.cursor++,!0;if(!(r[(s-=t)>>3]&1<<(7&s)))return this.cursor++,!0}return!1},out_grouping_b:function(r,t,i){if(this.cursor>this.limit_backward){var s=b.charCodeAt(this.cursor-1);if(i<s||s<t)return this.cursor--,!0;if(!(r[(s-=t)>>3]&1<<(7&s)))return this.cursor--,!0}return!1},eq_s:function(r,t){if(this.limit-this.cursor<r)return!1;for(var i=0;i<r;i++)if(b.charCodeAt(this.cursor+i)!=t.charCodeAt(i))return!1;return this.cursor+=r,!0},eq_s_b:function(r,t){if(this.cursor-this.limit_backward<r)return!1;for(var i=0;i<r;i++)if(b.charCodeAt(this.cursor-r+i)!=t.charCodeAt(i))return!1;return this.cursor-=r,!0},find_among:function(r,t){for(var i=0,s=t,e=this.cursor,n=this.limit,u=0,o=0,h=!1;;){for(var c=i+(s-i>>1),a=0,f=u<o?u:o,l=r[c],_=f;_<l.s_size;_++){if(e+f==n){a=-1;break}if(a=b.charCodeAt(e+f)-l.s[_])break;f++}if(a<0?(s=c,o=f):(i=c,u=f),s-i<=1){if(0<i||s==i||h)break;h=!0}}for(;;){if(u>=(l=r[i]).s_size){if(this.cursor=e+l.s_size,!l.method)return l.result;var m=l.method();if(this.cursor=e+l.s_size,m)return l.result}if((i=l.substring_i)<0)return 0}},find_among_b:function(r,t){for(var i=0,s=t,e=this.cursor,n=this.limit_backward,u=0,o=0,h=!1;;){for(var c=i+(s-i>>1),a=0,f=u<o?u:o,l=(_=r[c]).s_size-1-f;0<=l;l--){if(e-f==n){a=-1;break}if(a=b.charCodeAt(e-1-f)-_.s[l])break;f++}if(a<0?(s=c,o=f):(i=c,u=f),s-i<=1){if(0<i||s==i||h)break;h=!0}}for(;;){var _;if(u>=(_=r[i]).s_size){if(this.cursor=e-_.s_size,!_.method)return _.result;var m=_.method();if(this.cursor=e-_.s_size,m)return _.result}if((i=_.substring_i)<0)return 0}},replace_s:function(r,t,i){var s=i.length-(t-r);return b=b.substring(0,r)+i+b.substring(t),this.limit+=s,this.cursor>=t?this.cursor+=s:this.cursor>r&&(this.cursor=r),s},slice_check:function(){if(this.bra<0||this.bra>this.ket||this.ket>this.limit||this.limit>b.length)throw"faulty slice operation"},slice_from:function(r){this.slice_check(),this.replace_s(this.bra,this.ket,r)},slice_del:function(){this.slice_from("")},insert:function(r,t,i){var s=this.replace_s(r,t,i);r<=this.bra&&(this.bra+=s),r<=this.ket&&(this.ket+=s)},slice_to:function(){return this.slice_check(),b.substring(this.bra,this.ket)},eq_v_b:function(r){return this.eq_s_b(r.length,r)}}}},r.trimmerSupport={generateTrimmer:function(r){var t=new RegExp("^[^"+r+"]+"),i=new RegExp("[^"+r+"]+$");return function(r){return"function"==typeof r.update?r.update(function(r){return r.replace(t,"").replace(i,"")}):r.replace(t,"").replace(i,"")}}}}});

View File

@@ -1 +1,17 @@
/*!
* Lunr languages, `Swedish` language
* https://github.com/MihaiValentin/lunr-languages
*
* Copyright 2014, Mihai Valentin
* http://www.mozilla.org/MPL/
*/
/*!
* based on
* Snowball JavaScript Library v0.3
* http://code.google.com/p/urim/
* http://snowball.tartarus.org/
*
* Copyright 2010, Oleg Mazko
* http://www.mozilla.org/MPL/
*/
!function(e,r){"function"==typeof define&&define.amd?define(r):"object"==typeof exports?module.exports=r():r()(e.lunr)}(this,function(){return function(e){if(void 0===e)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===e.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");var r,l,n;e.sv=function(){this.pipeline.reset(),this.pipeline.add(e.sv.trimmer,e.sv.stopWordFilter,e.sv.stemmer),this.searchPipeline&&(this.searchPipeline.reset(),this.searchPipeline.add(e.sv.stemmer))},e.sv.wordCharacters="A-Za-zªºÀ-ÖØ-öø-ʸˠ-ˤᴀ-ᴥᴬ-ᵜᵢ-ᵥᵫ-ᵷᵹ-ᶾḀ-ỿⁱⁿₐ-ₜKÅℲⅎⅠ-ↈⱠ-ⱿꜢ-ꞇꞋ-ꞭꞰ-ꞷꟷ-ꟿꬰ-ꭚꭜ-ꭤff-stA--",e.sv.trimmer=e.trimmerSupport.generateTrimmer(e.sv.wordCharacters),e.Pipeline.registerFunction(e.sv.trimmer,"trimmer-sv"),e.sv.stemmer=(r=e.stemmerSupport.Among,l=e.stemmerSupport.SnowballProgram,n=new function(){var n,t,i=[new r("a",-1,1),new r("arna",0,1),new r("erna",0,1),new r("heterna",2,1),new r("orna",0,1),new r("ad",-1,1),new r("e",-1,1),new r("ade",6,1),new r("ande",6,1),new r("arne",6,1),new r("are",6,1),new r("aste",6,1),new r("en",-1,1),new r("anden",12,1),new r("aren",12,1),new r("heten",12,1),new r("ern",-1,1),new r("ar",-1,1),new r("er",-1,1),new r("heter",18,1),new r("or",-1,1),new r("s",-1,2),new r("as",21,1),new r("arnas",22,1),new r("ernas",22,1),new r("ornas",22,1),new r("es",21,1),new r("ades",26,1),new r("andes",26,1),new r("ens",21,1),new r("arens",29,1),new r("hetens",29,1),new r("erns",21,1),new r("at",-1,1),new r("andet",-1,1),new r("het",-1,1),new r("ast",-1,1)],s=[new r("dd",-1,-1),new r("gd",-1,-1),new r("nn",-1,-1),new r("dt",-1,-1),new r("gt",-1,-1),new r("kt",-1,-1),new r("tt",-1,-1)],a=[new r("ig",-1,1),new r("lig",0,1),new r("els",-1,1),new r("fullt",-1,3),new r("löst",-1,2)],o=[17,65,16,1,0,0,0,0,0,0,0,0,0,0,0,0,24,0,32],u=[119,127,149],m=new l;this.setCurrent=function(e){m.setCurrent(e)},this.getCurrent=function(){return m.getCurrent()},this.stem=function(){var e,r=m.cursor;return function(){var e,r=m.cursor+3;if(t=m.limit,0<=r||r<=m.limit){for(n=r;;){if(e=m.cursor,m.in_grouping(o,97,246)){m.cursor=e;break}if(m.cursor=e,m.cursor>=m.limit)return;m.cursor++}for(;!m.out_grouping(o,97,246);){if(m.cursor>=m.limit)return;m.cursor++}(t=m.cursor)<n&&(t=n)}}(),m.limit_backward=r,m.cursor=m.limit,function(){var e,r=m.limit_backward;if(m.cursor>=t&&(m.limit_backward=t,m.cursor=m.limit,m.ket=m.cursor,e=m.find_among_b(i,37),m.limit_backward=r,e))switch(m.bra=m.cursor,e){case 1:m.slice_del();break;case 2:m.in_grouping_b(u,98,121)&&m.slice_del()}}(),m.cursor=m.limit,e=m.limit_backward,m.cursor>=t&&(m.limit_backward=t,m.cursor=m.limit,m.find_among_b(s,7)&&(m.cursor=m.limit,m.ket=m.cursor,m.cursor>m.limit_backward&&(m.bra=--m.cursor,m.slice_del())),m.limit_backward=e),m.cursor=m.limit,function(){var e,r;if(m.cursor>=t){if(r=m.limit_backward,m.limit_backward=t,m.cursor=m.limit,m.ket=m.cursor,e=m.find_among_b(a,5))switch(m.bra=m.cursor,e){case 1:m.slice_del();break;case 2:m.slice_from("lös");break;case 3:m.slice_from("full")}m.limit_backward=r}}(),!0}},function(e){return"function"==typeof e.update?e.update(function(e){return n.setCurrent(e),n.stem(),n.getCurrent()}):(n.setCurrent(e),n.stem(),n.getCurrent())}),e.Pipeline.registerFunction(e.sv.stemmer,"stemmer-sv"),e.sv.stopWordFilter=e.generateStopWordFilter("alla allt att av blev bli blir blivit de dem den denna deras dess dessa det detta dig din dina ditt du där då efter ej eller en er era ert ett från för ha hade han hans har henne hennes hon honom hur här i icke ingen inom inte jag ju kan kunde man med mellan men mig min mina mitt mot mycket ni nu när någon något några och om oss på samma sedan sig sin sina sitta själv skulle som så sådan sådana sådant till under upp ut utan vad var vara varför varit varje vars vart vem vi vid vilka vilkas vilken vilket vår våra vårt än är åt över".split(" ")),e.Pipeline.registerFunction(e.sv.stopWordFilter,"stopWordFilter-sv")}});

View File

@@ -1 +1,17 @@
/*!
* Lunr languages, `Thai` language
* https://github.com/MihaiValentin/lunr-languages
*
* Copyright 2017, Keerati Thiwanruk
* http://www.mozilla.org/MPL/
*/
/*!
* based on
* Snowball JavaScript Library v0.3
* http://code.google.com/p/urim/
* http://snowball.tartarus.org/
*
* Copyright 2010, Oleg Mazko
* http://www.mozilla.org/MPL/
*/
!function(e,r){"function"==typeof define&&define.amd?define(r):"object"==typeof exports?module.exports=r():r()(e.lunr)}(this,function(){return function(t){if(void 0===t)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===t.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");var i="2"==t.version[0];t.th=function(){this.pipeline.reset(),this.pipeline.add(t.th.trimmer),i?this.tokenizer=t.th.tokenizer:(t.tokenizer&&(t.tokenizer=t.th.tokenizer),this.tokenizerFn&&(this.tokenizerFn=t.th.tokenizer))},t.th.wordCharacters="[฀-๿]",t.th.trimmer=t.trimmerSupport.generateTrimmer(t.th.wordCharacters),t.Pipeline.registerFunction(t.th.trimmer,"trimmer-th");var n=t.wordcut;n.init(),t.th.tokenizer=function(e){if(!arguments.length||null==e||null==e)return[];if(Array.isArray(e))return e.map(function(e){return i?new t.Token(e):e});var r=e.toString().replace(/^\s+/,"");return n.cut(r).split("|")}}});

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,17 @@
/*!
* Lunr languages, `Vietnamese` language
* https://github.com/MihaiValentin/lunr-languages
*
* Copyright 2017, Keerati Thiwanruk
* http://www.mozilla.org/MPL/
*/
/*!
* based on
* Snowball JavaScript Library v0.3
* http://code.google.com/p/urim/
* http://snowball.tartarus.org/
*
* Copyright 2010, Oleg Mazko
* http://www.mozilla.org/MPL/
*/
!function(e,r){"function"==typeof define&&define.amd?define(r):"object"==typeof exports?module.exports=r():r()(e.lunr)}(this,function(){return function(e){if(void 0===e)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===e.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");e.vi=function(){this.pipeline.reset(),this.pipeline.add(e.vi.stopWordFilter,e.vi.trimmer)},e.vi.wordCharacters="[A-Za-ẓ̀͐́͑̉̃̓ÂâÊêÔôĂ-ăĐ-đƠ-ơƯ-ư]",e.vi.trimmer=e.trimmerSupport.generateTrimmer(e.vi.wordCharacters),e.Pipeline.registerFunction(e.vi.trimmer,"trimmer-vi"),e.vi.stopWordFilter=e.generateStopWordFilter("là cái nhưng mà".split(" "))}});

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -1,562 +0,0 @@
<!doctype html>
<html lang="en" class="no-js">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta http-equiv="x-ua-compatible" content="ie=edge">
<meta name="lang:clipboard.copy" content="Copy to clipboard">
<meta name="lang:clipboard.copied" content="Copied to clipboard">
<meta name="lang:search.language" content="en">
<meta name="lang:search.pipeline.stopwords" content="True">
<meta name="lang:search.pipeline.trimmer" content="True">
<meta name="lang:search.result.none" content="No matching documents">
<meta name="lang:search.result.one" content="1 matching document">
<meta name="lang:search.result.other" content="# matching documents">
<meta name="lang:search.tokenizer" content="[\s\-]+">
<link rel="shortcut icon" href="../assets/images/favicon.png">
<meta name="generator" content="mkdocs-1.0.4, mkdocs-material-4.2.0">
<title>Convert - Yq</title>
<link rel="stylesheet" href="../assets/stylesheets/application.750b69bd.css">
<script src="../assets/javascripts/modernizr.74668098.js"></script>
<link href="https://fonts.gstatic.com" rel="preconnect" crossorigin>
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:300,400,400i,700|Roboto+Mono">
<style>body,input{font-family:"Roboto","Helvetica Neue",Helvetica,Arial,sans-serif}code,kbd,pre{font-family:"Roboto Mono","Courier New",Courier,monospace}</style>
<link rel="stylesheet" href="../assets/fonts/material-icons.css">
</head>
<body dir="ltr">
<svg class="md-svg">
<defs>
<svg xmlns="http://www.w3.org/2000/svg" width="416" height="448"
viewBox="0 0 416 448" id="__github">
<path fill="currentColor" d="M160 304q0 10-3.125 20.5t-10.75 19-18.125
8.5-18.125-8.5-10.75-19-3.125-20.5 3.125-20.5 10.75-19 18.125-8.5
18.125 8.5 10.75 19 3.125 20.5zM320 304q0 10-3.125 20.5t-10.75
19-18.125 8.5-18.125-8.5-10.75-19-3.125-20.5 3.125-20.5 10.75-19
18.125-8.5 18.125 8.5 10.75 19 3.125 20.5zM360
304q0-30-17.25-51t-46.75-21q-10.25 0-48.75 5.25-17.75 2.75-39.25
2.75t-39.25-2.75q-38-5.25-48.75-5.25-29.5 0-46.75 21t-17.25 51q0 22 8
38.375t20.25 25.75 30.5 15 35 7.375 37.25 1.75h42q20.5 0
37.25-1.75t35-7.375 30.5-15 20.25-25.75 8-38.375zM416 260q0 51.75-15.25
82.75-9.5 19.25-26.375 33.25t-35.25 21.5-42.5 11.875-42.875 5.5-41.75
1.125q-19.5 0-35.5-0.75t-36.875-3.125-38.125-7.5-34.25-12.875-30.25-20.25-21.5-28.75q-15.5-30.75-15.5-82.75
0-59.25 34-99-6.75-20.5-6.75-42.5 0-29 12.75-54.5 27 0 47.5 9.875t47.25
30.875q36.75-8.75 77.25-8.75 37 0 70 8 26.25-20.5
46.75-30.25t47.25-9.75q12.75 25.5 12.75 54.5 0 21.75-6.75 42 34 40 34
99.5z" />
</svg>
</defs>
</svg>
<input class="md-toggle" data-md-toggle="drawer" type="checkbox" id="__drawer" autocomplete="off">
<input class="md-toggle" data-md-toggle="search" type="checkbox" id="__search" autocomplete="off">
<label class="md-overlay" data-md-component="overlay" for="__drawer"></label>
<a href="#yaml-to-json" tabindex="1" class="md-skip">
Skip to content
</a>
<header class="md-header" data-md-component="header">
<nav class="md-header-nav md-grid">
<div class="md-flex">
<div class="md-flex__cell md-flex__cell--shrink">
<a href=".." title="Yq" class="md-header-nav__button md-logo">
<i class="md-icon"></i>
</a>
</div>
<div class="md-flex__cell md-flex__cell--shrink">
<label class="md-icon md-icon--menu md-header-nav__button" for="__drawer"></label>
</div>
<div class="md-flex__cell md-flex__cell--stretch">
<div class="md-flex__ellipsis md-header-nav__title" data-md-component="title">
<span class="md-header-nav__topic">
Yq
</span>
<span class="md-header-nav__topic">
Convert
</span>
</div>
</div>
<div class="md-flex__cell md-flex__cell--shrink">
<label class="md-icon md-icon--search md-header-nav__button" for="__search"></label>
<div class="md-search" data-md-component="search" role="dialog">
<label class="md-search__overlay" for="__search"></label>
<div class="md-search__inner" role="search">
<form class="md-search__form" name="search">
<input type="text" class="md-search__input" name="query" placeholder="Search" autocapitalize="off" autocorrect="off" autocomplete="off" spellcheck="false" data-md-component="query" data-md-state="active">
<label class="md-icon md-search__icon" for="__search"></label>
<button type="reset" class="md-icon md-search__icon" data-md-component="reset" tabindex="-1">
&#xE5CD;
</button>
</form>
<div class="md-search__output">
<div class="md-search__scrollwrap" data-md-scrollfix>
<div class="md-search-result" data-md-component="result">
<div class="md-search-result__meta">
Type to start searching
</div>
<ol class="md-search-result__list"></ol>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="md-flex__cell md-flex__cell--shrink">
<div class="md-header-nav__source">
<a href="https://github.com/mikefarah/yq/" title="Go to repository" class="md-source" data-md-source="github">
<div class="md-source__icon">
<svg viewBox="0 0 24 24" width="24" height="24">
<use xlink:href="#__github" width="24" height="24"></use>
</svg>
</div>
<div class="md-source__repository">
mikefarah/yq
</div>
</a>
</div>
</div>
</div>
</nav>
</header>
<div class="md-container">
<main class="md-main">
<div class="md-main__inner md-grid" data-md-component="container">
<div class="md-sidebar md-sidebar--primary" data-md-component="navigation">
<div class="md-sidebar__scrollwrap">
<div class="md-sidebar__inner">
<nav class="md-nav md-nav--primary" data-md-level="0">
<label class="md-nav__title md-nav__title--site" for="__drawer">
<a href=".." title="Yq" class="md-nav__button md-logo">
<i class="md-icon"></i>
</a>
Yq
</label>
<div class="md-nav__source">
<a href="https://github.com/mikefarah/yq/" title="Go to repository" class="md-source" data-md-source="github">
<div class="md-source__icon">
<svg viewBox="0 0 24 24" width="24" height="24">
<use xlink:href="#__github" width="24" height="24"></use>
</svg>
</div>
<div class="md-source__repository">
mikefarah/yq
</div>
</a>
</div>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href=".." title="Install" class="md-nav__link">
Install
</a>
</li>
<li class="md-nav__item">
<a href="../read/" title="Read" class="md-nav__link">
Read
</a>
</li>
<li class="md-nav__item">
<a href="../path_expressions/" title="Path Expressions" class="md-nav__link">
Path Expressions
</a>
</li>
<li class="md-nav__item">
<a href="../write/" title="Write/Update" class="md-nav__link">
Write/Update
</a>
</li>
<li class="md-nav__item">
<a href="../prefix/" title="Prefix" class="md-nav__link">
Prefix
</a>
</li>
<li class="md-nav__item">
<a href="../delete/" title="Delete" class="md-nav__link">
Delete
</a>
</li>
<li class="md-nav__item">
<a href="../create/" title="Create" class="md-nav__link">
Create
</a>
</li>
<li class="md-nav__item md-nav__item--active">
<input class="md-toggle md-nav__toggle" data-md-toggle="toc" type="checkbox" id="__toc">
<label class="md-nav__link md-nav__link--active" for="__toc">
Convert
</label>
<a href="./" title="Convert" class="md-nav__link md-nav__link--active">
Convert
</a>
<nav class="md-nav md-nav--secondary">
<label class="md-nav__title" for="__toc">Table of contents</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="#yaml-to-json" title="Yaml to Json" class="md-nav__link">
Yaml to Json
</a>
</li>
<li class="md-nav__item">
<a href="#json-to-yaml" title="Json to Yaml" class="md-nav__link">
Json to Yaml
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="../merge/" title="Merge" class="md-nav__link">
Merge
</a>
</li>
</ul>
</nav>
</div>
</div>
</div>
<div class="md-sidebar md-sidebar--secondary" data-md-component="toc">
<div class="md-sidebar__scrollwrap">
<div class="md-sidebar__inner">
<nav class="md-nav md-nav--secondary">
<label class="md-nav__title" for="__toc">Table of contents</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="#yaml-to-json" title="Yaml to Json" class="md-nav__link">
Yaml to Json
</a>
</li>
<li class="md-nav__item">
<a href="#json-to-yaml" title="Json to Yaml" class="md-nav__link">
Json to Yaml
</a>
</li>
</ul>
</nav>
</div>
</div>
</div>
<div class="md-content">
<article class="md-content__inner md-typeset">
<a href="https://github.com/mikefarah/yq/edit/master/docs/convert.md" title="Edit this page" class="md-icon md-content__icon">&#xE3C9;</a>
<h1>Convert</h1>
<h3 id="yaml-to-json">Yaml to Json<a class="headerlink" href="#yaml-to-json" title="Permanent link">&para;</a></h3>
<p>To convert output to json, use the --tojson (or -j) flag. This is supported by all commands.</p>
<p>Each matching yaml node will be converted to json and printed out on a separate line.</p>
<p>Given a sample.yaml file of:</p>
<pre><code class="yaml">b:
c: 2
</code></pre>
<p>then</p>
<pre><code class="bash">yq r -j sample.yaml
</code></pre>
<p>will output</p>
<pre><code class="json">{&quot;b&quot;:{&quot;c&quot;:2}}
</code></pre>
<p>Given a sample.yaml file of:</p>
<pre><code class="yaml">bob:
c: 2
bab:
c: 5
</code></pre>
<p>then</p>
<pre><code class="bash">yq r -j sample.yaml b*
</code></pre>
<p>will output</p>
<pre><code class="json">{&quot;c&quot;:2}
{&quot;c&quot;:5}
</code></pre>
<h3 id="json-to-yaml">Json to Yaml<a class="headerlink" href="#json-to-yaml" title="Permanent link">&para;</a></h3>
<p>To read in json, just pass in a json file instead of yaml, it will just work :)</p>
<p>e.g given a json file</p>
<pre><code class="json">{&quot;a&quot;:&quot;Easy! as one two three&quot;,&quot;b&quot;:{&quot;c&quot;:2,&quot;d&quot;:[3,4]}}
</code></pre>
<p>then</p>
<pre><code class="bash">yq r sample.json
</code></pre>
<p>will output</p>
<pre><code class="yaml">a: Easy! as one two three
b:
c: 2
d:
- 3
- 4
</code></pre>
</article>
</div>
</div>
</main>
<footer class="md-footer">
<div class="md-footer-nav">
<nav class="md-footer-nav__inner md-grid">
<a href="../create/" title="Create" class="md-flex md-footer-nav__link md-footer-nav__link--prev" rel="prev">
<div class="md-flex__cell md-flex__cell--shrink">
<i class="md-icon md-icon--arrow-back md-footer-nav__button"></i>
</div>
<div class="md-flex__cell md-flex__cell--stretch md-footer-nav__title">
<span class="md-flex__ellipsis">
<span class="md-footer-nav__direction">
Previous
</span>
Create
</span>
</div>
</a>
<a href="../merge/" title="Merge" class="md-flex md-footer-nav__link md-footer-nav__link--next" rel="next">
<div class="md-flex__cell md-flex__cell--stretch md-footer-nav__title">
<span class="md-flex__ellipsis">
<span class="md-footer-nav__direction">
Next
</span>
Merge
</span>
</div>
<div class="md-flex__cell md-flex__cell--shrink">
<i class="md-icon md-icon--arrow-forward md-footer-nav__button"></i>
</div>
</a>
</nav>
</div>
<div class="md-footer-meta md-typeset">
<div class="md-footer-meta__inner md-grid">
<div class="md-footer-copyright">
powered by
<a href="https://www.mkdocs.org">MkDocs</a>
and
<a href="https://squidfunk.github.io/mkdocs-material/">
Material for MkDocs</a>
</div>
<div class="md-footer-social">
<link rel="stylesheet" href="../assets/fonts/font-awesome.css">
<a href="https://github.com/mikefarah" class="md-footer-social__link fa fa-github"></a>
<a href="https://www.linkedin.com/in/mike-farah-b5a75b2/" class="md-footer-social__link fa fa-linkedin"></a>
</div>
</div>
</div>
</footer>
</div>
<script src="../assets/javascripts/application.39abc4af.js"></script>
<script>app.initialize({version:"1.0.4",url:{base:".."}})</script>
</body>
</html>

View File

@@ -1,550 +0,0 @@
<!doctype html>
<html lang="en" class="no-js">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta http-equiv="x-ua-compatible" content="ie=edge">
<meta name="lang:clipboard.copy" content="Copy to clipboard">
<meta name="lang:clipboard.copied" content="Copied to clipboard">
<meta name="lang:search.language" content="en">
<meta name="lang:search.pipeline.stopwords" content="True">
<meta name="lang:search.pipeline.trimmer" content="True">
<meta name="lang:search.result.none" content="No matching documents">
<meta name="lang:search.result.one" content="1 matching document">
<meta name="lang:search.result.other" content="# matching documents">
<meta name="lang:search.tokenizer" content="[\s\-]+">
<link rel="shortcut icon" href="../assets/images/favicon.png">
<meta name="generator" content="mkdocs-1.0.4, mkdocs-material-4.2.0">
<title>Create - Yq</title>
<link rel="stylesheet" href="../assets/stylesheets/application.750b69bd.css">
<script src="../assets/javascripts/modernizr.74668098.js"></script>
<link href="https://fonts.gstatic.com" rel="preconnect" crossorigin>
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:300,400,400i,700|Roboto+Mono">
<style>body,input{font-family:"Roboto","Helvetica Neue",Helvetica,Arial,sans-serif}code,kbd,pre{font-family:"Roboto Mono","Courier New",Courier,monospace}</style>
<link rel="stylesheet" href="../assets/fonts/material-icons.css">
</head>
<body dir="ltr">
<svg class="md-svg">
<defs>
<svg xmlns="http://www.w3.org/2000/svg" width="416" height="448"
viewBox="0 0 416 448" id="__github">
<path fill="currentColor" d="M160 304q0 10-3.125 20.5t-10.75 19-18.125
8.5-18.125-8.5-10.75-19-3.125-20.5 3.125-20.5 10.75-19 18.125-8.5
18.125 8.5 10.75 19 3.125 20.5zM320 304q0 10-3.125 20.5t-10.75
19-18.125 8.5-18.125-8.5-10.75-19-3.125-20.5 3.125-20.5 10.75-19
18.125-8.5 18.125 8.5 10.75 19 3.125 20.5zM360
304q0-30-17.25-51t-46.75-21q-10.25 0-48.75 5.25-17.75 2.75-39.25
2.75t-39.25-2.75q-38-5.25-48.75-5.25-29.5 0-46.75 21t-17.25 51q0 22 8
38.375t20.25 25.75 30.5 15 35 7.375 37.25 1.75h42q20.5 0
37.25-1.75t35-7.375 30.5-15 20.25-25.75 8-38.375zM416 260q0 51.75-15.25
82.75-9.5 19.25-26.375 33.25t-35.25 21.5-42.5 11.875-42.875 5.5-41.75
1.125q-19.5 0-35.5-0.75t-36.875-3.125-38.125-7.5-34.25-12.875-30.25-20.25-21.5-28.75q-15.5-30.75-15.5-82.75
0-59.25 34-99-6.75-20.5-6.75-42.5 0-29 12.75-54.5 27 0 47.5 9.875t47.25
30.875q36.75-8.75 77.25-8.75 37 0 70 8 26.25-20.5
46.75-30.25t47.25-9.75q12.75 25.5 12.75 54.5 0 21.75-6.75 42 34 40 34
99.5z" />
</svg>
</defs>
</svg>
<input class="md-toggle" data-md-toggle="drawer" type="checkbox" id="__drawer" autocomplete="off">
<input class="md-toggle" data-md-toggle="search" type="checkbox" id="__search" autocomplete="off">
<label class="md-overlay" data-md-component="overlay" for="__drawer"></label>
<a href="#creating-a-simple-yaml-file" tabindex="1" class="md-skip">
Skip to content
</a>
<header class="md-header" data-md-component="header">
<nav class="md-header-nav md-grid">
<div class="md-flex">
<div class="md-flex__cell md-flex__cell--shrink">
<a href=".." title="Yq" class="md-header-nav__button md-logo">
<i class="md-icon"></i>
</a>
</div>
<div class="md-flex__cell md-flex__cell--shrink">
<label class="md-icon md-icon--menu md-header-nav__button" for="__drawer"></label>
</div>
<div class="md-flex__cell md-flex__cell--stretch">
<div class="md-flex__ellipsis md-header-nav__title" data-md-component="title">
<span class="md-header-nav__topic">
Yq
</span>
<span class="md-header-nav__topic">
Create
</span>
</div>
</div>
<div class="md-flex__cell md-flex__cell--shrink">
<label class="md-icon md-icon--search md-header-nav__button" for="__search"></label>
<div class="md-search" data-md-component="search" role="dialog">
<label class="md-search__overlay" for="__search"></label>
<div class="md-search__inner" role="search">
<form class="md-search__form" name="search">
<input type="text" class="md-search__input" name="query" placeholder="Search" autocapitalize="off" autocorrect="off" autocomplete="off" spellcheck="false" data-md-component="query" data-md-state="active">
<label class="md-icon md-search__icon" for="__search"></label>
<button type="reset" class="md-icon md-search__icon" data-md-component="reset" tabindex="-1">
&#xE5CD;
</button>
</form>
<div class="md-search__output">
<div class="md-search__scrollwrap" data-md-scrollfix>
<div class="md-search-result" data-md-component="result">
<div class="md-search-result__meta">
Type to start searching
</div>
<ol class="md-search-result__list"></ol>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="md-flex__cell md-flex__cell--shrink">
<div class="md-header-nav__source">
<a href="https://github.com/mikefarah/yq/" title="Go to repository" class="md-source" data-md-source="github">
<div class="md-source__icon">
<svg viewBox="0 0 24 24" width="24" height="24">
<use xlink:href="#__github" width="24" height="24"></use>
</svg>
</div>
<div class="md-source__repository">
mikefarah/yq
</div>
</a>
</div>
</div>
</div>
</nav>
</header>
<div class="md-container">
<main class="md-main">
<div class="md-main__inner md-grid" data-md-component="container">
<div class="md-sidebar md-sidebar--primary" data-md-component="navigation">
<div class="md-sidebar__scrollwrap">
<div class="md-sidebar__inner">
<nav class="md-nav md-nav--primary" data-md-level="0">
<label class="md-nav__title md-nav__title--site" for="__drawer">
<a href=".." title="Yq" class="md-nav__button md-logo">
<i class="md-icon"></i>
</a>
Yq
</label>
<div class="md-nav__source">
<a href="https://github.com/mikefarah/yq/" title="Go to repository" class="md-source" data-md-source="github">
<div class="md-source__icon">
<svg viewBox="0 0 24 24" width="24" height="24">
<use xlink:href="#__github" width="24" height="24"></use>
</svg>
</div>
<div class="md-source__repository">
mikefarah/yq
</div>
</a>
</div>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href=".." title="Install" class="md-nav__link">
Install
</a>
</li>
<li class="md-nav__item">
<a href="../read/" title="Read" class="md-nav__link">
Read
</a>
</li>
<li class="md-nav__item">
<a href="../path_expressions/" title="Path Expressions" class="md-nav__link">
Path Expressions
</a>
</li>
<li class="md-nav__item">
<a href="../write/" title="Write/Update" class="md-nav__link">
Write/Update
</a>
</li>
<li class="md-nav__item">
<a href="../prefix/" title="Prefix" class="md-nav__link">
Prefix
</a>
</li>
<li class="md-nav__item">
<a href="../delete/" title="Delete" class="md-nav__link">
Delete
</a>
</li>
<li class="md-nav__item md-nav__item--active">
<input class="md-toggle md-nav__toggle" data-md-toggle="toc" type="checkbox" id="__toc">
<label class="md-nav__link md-nav__link--active" for="__toc">
Create
</label>
<a href="./" title="Create" class="md-nav__link md-nav__link--active">
Create
</a>
<nav class="md-nav md-nav--secondary">
<label class="md-nav__title" for="__toc">Table of contents</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="#creating-a-simple-yaml-file" title="Creating a simple yaml file" class="md-nav__link">
Creating a simple yaml file
</a>
</li>
<li class="md-nav__item">
<a href="#creating-using-a-create-script" title="Creating using a create script" class="md-nav__link">
Creating using a create script
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="../convert/" title="Convert" class="md-nav__link">
Convert
</a>
</li>
<li class="md-nav__item">
<a href="../merge/" title="Merge" class="md-nav__link">
Merge
</a>
</li>
</ul>
</nav>
</div>
</div>
</div>
<div class="md-sidebar md-sidebar--secondary" data-md-component="toc">
<div class="md-sidebar__scrollwrap">
<div class="md-sidebar__inner">
<nav class="md-nav md-nav--secondary">
<label class="md-nav__title" for="__toc">Table of contents</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="#creating-a-simple-yaml-file" title="Creating a simple yaml file" class="md-nav__link">
Creating a simple yaml file
</a>
</li>
<li class="md-nav__item">
<a href="#creating-using-a-create-script" title="Creating using a create script" class="md-nav__link">
Creating using a create script
</a>
</li>
</ul>
</nav>
</div>
</div>
</div>
<div class="md-content">
<article class="md-content__inner md-typeset">
<a href="https://github.com/mikefarah/yq/edit/master/docs/create.md" title="Edit this page" class="md-icon md-content__icon">&#xE3C9;</a>
<h1>Create</h1>
<pre><code>yq n &lt;path_expression&gt; &lt;new value&gt;
</code></pre>
<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>
<p>See docs for <a href="../path_expressions/">path expression</a></p>
<h3 id="creating-a-simple-yaml-file">Creating a simple yaml file<a class="headerlink" href="#creating-a-simple-yaml-file" title="Permanent link">&para;</a></h3>
<pre><code class="bash">yq n b.c cat
</code></pre>
<p>will output:</p>
<pre><code class="yaml">b:
c: cat
</code></pre>
<h3 id="creating-using-a-create-script">Creating using a create script<a class="headerlink" href="#creating-using-a-create-script" title="Permanent link">&para;</a></h3>
<p>Create scripts follow the same format as the update scripts.</p>
<p>Given a script create_instructions.yaml of:</p>
<pre><code class="yaml">- command: update
path: b.c
value:
#great
things: frog # wow!
</code></pre>
<p>then</p>
<pre><code class="bash">yq n -s create_instructions.yaml
</code></pre>
<p>will output:</p>
<pre><code class="yaml">b:
c:
#great
things: frog # wow!
</code></pre>
<p>You can also pipe the instructions in:</p>
<pre><code class="bash">cat create_instructions.yaml | yq n -s -
</code></pre>
</article>
</div>
</div>
</main>
<footer class="md-footer">
<div class="md-footer-nav">
<nav class="md-footer-nav__inner md-grid">
<a href="../delete/" title="Delete" class="md-flex md-footer-nav__link md-footer-nav__link--prev" rel="prev">
<div class="md-flex__cell md-flex__cell--shrink">
<i class="md-icon md-icon--arrow-back md-footer-nav__button"></i>
</div>
<div class="md-flex__cell md-flex__cell--stretch md-footer-nav__title">
<span class="md-flex__ellipsis">
<span class="md-footer-nav__direction">
Previous
</span>
Delete
</span>
</div>
</a>
<a href="../convert/" title="Convert" class="md-flex md-footer-nav__link md-footer-nav__link--next" rel="next">
<div class="md-flex__cell md-flex__cell--stretch md-footer-nav__title">
<span class="md-flex__ellipsis">
<span class="md-footer-nav__direction">
Next
</span>
Convert
</span>
</div>
<div class="md-flex__cell md-flex__cell--shrink">
<i class="md-icon md-icon--arrow-forward md-footer-nav__button"></i>
</div>
</a>
</nav>
</div>
<div class="md-footer-meta md-typeset">
<div class="md-footer-meta__inner md-grid">
<div class="md-footer-copyright">
powered by
<a href="https://www.mkdocs.org">MkDocs</a>
and
<a href="https://squidfunk.github.io/mkdocs-material/">
Material for MkDocs</a>
</div>
<div class="md-footer-social">
<link rel="stylesheet" href="../assets/fonts/font-awesome.css">
<a href="https://github.com/mikefarah" class="md-footer-social__link fa fa-github"></a>
<a href="https://www.linkedin.com/in/mike-farah-b5a75b2/" class="md-footer-social__link fa fa-linkedin"></a>
</div>
</div>
</div>
</footer>
</div>
<script src="../assets/javascripts/application.39abc4af.js"></script>
<script>app.initialize({version:"1.0.4",url:{base:".."}})</script>
</body>
</html>

View File

@@ -1,606 +0,0 @@
<!doctype html>
<html lang="en" class="no-js">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta http-equiv="x-ua-compatible" content="ie=edge">
<meta name="lang:clipboard.copy" content="Copy to clipboard">
<meta name="lang:clipboard.copied" content="Copied to clipboard">
<meta name="lang:search.language" content="en">
<meta name="lang:search.pipeline.stopwords" content="True">
<meta name="lang:search.pipeline.trimmer" content="True">
<meta name="lang:search.result.none" content="No matching documents">
<meta name="lang:search.result.one" content="1 matching document">
<meta name="lang:search.result.other" content="# matching documents">
<meta name="lang:search.tokenizer" content="[\s\-]+">
<link rel="shortcut icon" href="../assets/images/favicon.png">
<meta name="generator" content="mkdocs-1.0.4, mkdocs-material-4.2.0">
<title>Delete - Yq</title>
<link rel="stylesheet" href="../assets/stylesheets/application.750b69bd.css">
<script src="../assets/javascripts/modernizr.74668098.js"></script>
<link href="https://fonts.gstatic.com" rel="preconnect" crossorigin>
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:300,400,400i,700|Roboto+Mono">
<style>body,input{font-family:"Roboto","Helvetica Neue",Helvetica,Arial,sans-serif}code,kbd,pre{font-family:"Roboto Mono","Courier New",Courier,monospace}</style>
<link rel="stylesheet" href="../assets/fonts/material-icons.css">
</head>
<body dir="ltr">
<svg class="md-svg">
<defs>
<svg xmlns="http://www.w3.org/2000/svg" width="416" height="448"
viewBox="0 0 416 448" id="__github">
<path fill="currentColor" d="M160 304q0 10-3.125 20.5t-10.75 19-18.125
8.5-18.125-8.5-10.75-19-3.125-20.5 3.125-20.5 10.75-19 18.125-8.5
18.125 8.5 10.75 19 3.125 20.5zM320 304q0 10-3.125 20.5t-10.75
19-18.125 8.5-18.125-8.5-10.75-19-3.125-20.5 3.125-20.5 10.75-19
18.125-8.5 18.125 8.5 10.75 19 3.125 20.5zM360
304q0-30-17.25-51t-46.75-21q-10.25 0-48.75 5.25-17.75 2.75-39.25
2.75t-39.25-2.75q-38-5.25-48.75-5.25-29.5 0-46.75 21t-17.25 51q0 22 8
38.375t20.25 25.75 30.5 15 35 7.375 37.25 1.75h42q20.5 0
37.25-1.75t35-7.375 30.5-15 20.25-25.75 8-38.375zM416 260q0 51.75-15.25
82.75-9.5 19.25-26.375 33.25t-35.25 21.5-42.5 11.875-42.875 5.5-41.75
1.125q-19.5 0-35.5-0.75t-36.875-3.125-38.125-7.5-34.25-12.875-30.25-20.25-21.5-28.75q-15.5-30.75-15.5-82.75
0-59.25 34-99-6.75-20.5-6.75-42.5 0-29 12.75-54.5 27 0 47.5 9.875t47.25
30.875q36.75-8.75 77.25-8.75 37 0 70 8 26.25-20.5
46.75-30.25t47.25-9.75q12.75 25.5 12.75 54.5 0 21.75-6.75 42 34 40 34
99.5z" />
</svg>
</defs>
</svg>
<input class="md-toggle" data-md-toggle="drawer" type="checkbox" id="__drawer" autocomplete="off">
<input class="md-toggle" data-md-toggle="search" type="checkbox" id="__search" autocomplete="off">
<label class="md-overlay" data-md-component="overlay" for="__drawer"></label>
<a href="#from-stdin" tabindex="1" class="md-skip">
Skip to content
</a>
<header class="md-header" data-md-component="header">
<nav class="md-header-nav md-grid">
<div class="md-flex">
<div class="md-flex__cell md-flex__cell--shrink">
<a href=".." title="Yq" class="md-header-nav__button md-logo">
<i class="md-icon"></i>
</a>
</div>
<div class="md-flex__cell md-flex__cell--shrink">
<label class="md-icon md-icon--menu md-header-nav__button" for="__drawer"></label>
</div>
<div class="md-flex__cell md-flex__cell--stretch">
<div class="md-flex__ellipsis md-header-nav__title" data-md-component="title">
<span class="md-header-nav__topic">
Yq
</span>
<span class="md-header-nav__topic">
Delete
</span>
</div>
</div>
<div class="md-flex__cell md-flex__cell--shrink">
<label class="md-icon md-icon--search md-header-nav__button" for="__search"></label>
<div class="md-search" data-md-component="search" role="dialog">
<label class="md-search__overlay" for="__search"></label>
<div class="md-search__inner" role="search">
<form class="md-search__form" name="search">
<input type="text" class="md-search__input" name="query" placeholder="Search" autocapitalize="off" autocorrect="off" autocomplete="off" spellcheck="false" data-md-component="query" data-md-state="active">
<label class="md-icon md-search__icon" for="__search"></label>
<button type="reset" class="md-icon md-search__icon" data-md-component="reset" tabindex="-1">
&#xE5CD;
</button>
</form>
<div class="md-search__output">
<div class="md-search__scrollwrap" data-md-scrollfix>
<div class="md-search-result" data-md-component="result">
<div class="md-search-result__meta">
Type to start searching
</div>
<ol class="md-search-result__list"></ol>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="md-flex__cell md-flex__cell--shrink">
<div class="md-header-nav__source">
<a href="https://github.com/mikefarah/yq/" title="Go to repository" class="md-source" data-md-source="github">
<div class="md-source__icon">
<svg viewBox="0 0 24 24" width="24" height="24">
<use xlink:href="#__github" width="24" height="24"></use>
</svg>
</div>
<div class="md-source__repository">
mikefarah/yq
</div>
</a>
</div>
</div>
</div>
</nav>
</header>
<div class="md-container">
<main class="md-main">
<div class="md-main__inner md-grid" data-md-component="container">
<div class="md-sidebar md-sidebar--primary" data-md-component="navigation">
<div class="md-sidebar__scrollwrap">
<div class="md-sidebar__inner">
<nav class="md-nav md-nav--primary" data-md-level="0">
<label class="md-nav__title md-nav__title--site" for="__drawer">
<a href=".." title="Yq" class="md-nav__button md-logo">
<i class="md-icon"></i>
</a>
Yq
</label>
<div class="md-nav__source">
<a href="https://github.com/mikefarah/yq/" title="Go to repository" class="md-source" data-md-source="github">
<div class="md-source__icon">
<svg viewBox="0 0 24 24" width="24" height="24">
<use xlink:href="#__github" width="24" height="24"></use>
</svg>
</div>
<div class="md-source__repository">
mikefarah/yq
</div>
</a>
</div>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href=".." title="Install" class="md-nav__link">
Install
</a>
</li>
<li class="md-nav__item">
<a href="../read/" title="Read" class="md-nav__link">
Read
</a>
</li>
<li class="md-nav__item">
<a href="../path_expressions/" title="Path Expressions" class="md-nav__link">
Path Expressions
</a>
</li>
<li class="md-nav__item">
<a href="../write/" title="Write/Update" class="md-nav__link">
Write/Update
</a>
</li>
<li class="md-nav__item">
<a href="../prefix/" title="Prefix" class="md-nav__link">
Prefix
</a>
</li>
<li class="md-nav__item md-nav__item--active">
<input class="md-toggle md-nav__toggle" data-md-toggle="toc" type="checkbox" id="__toc">
<label class="md-nav__link md-nav__link--active" for="__toc">
Delete
</label>
<a href="./" title="Delete" class="md-nav__link md-nav__link--active">
Delete
</a>
<nav class="md-nav md-nav--secondary">
<label class="md-nav__title" for="__toc">Table of contents</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="#from-stdin" title="From STDIN" class="md-nav__link">
From STDIN
</a>
</li>
<li class="md-nav__item">
<a href="#deleting-nodes-in-place" title="Deleting nodes in-place" class="md-nav__link">
Deleting nodes in-place
</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>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="../create/" title="Create" class="md-nav__link">
Create
</a>
</li>
<li class="md-nav__item">
<a href="../convert/" title="Convert" class="md-nav__link">
Convert
</a>
</li>
<li class="md-nav__item">
<a href="../merge/" title="Merge" class="md-nav__link">
Merge
</a>
</li>
</ul>
</nav>
</div>
</div>
</div>
<div class="md-sidebar md-sidebar--secondary" data-md-component="toc">
<div class="md-sidebar__scrollwrap">
<div class="md-sidebar__inner">
<nav class="md-nav md-nav--secondary">
<label class="md-nav__title" for="__toc">Table of contents</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="#from-stdin" title="From STDIN" class="md-nav__link">
From STDIN
</a>
</li>
<li class="md-nav__item">
<a href="#deleting-nodes-in-place" title="Deleting nodes in-place" class="md-nav__link">
Deleting nodes in-place
</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>
</ul>
</nav>
</div>
</div>
</div>
<div class="md-content">
<article class="md-content__inner md-typeset">
<a href="https://github.com/mikefarah/yq/edit/master/docs/delete.md" title="Edit this page" class="md-icon md-content__icon">&#xE3C9;</a>
<h1>Delete</h1>
<pre><code>yq delete &lt;yaml_file|-&gt; &lt;path_expression&gt;
</code></pre>
<p>The delete command will delete all the matching nodes for the path expression in the given yaml input.</p>
<p>See docs for <a href="../path_expressions/">path expression</a> for more details.</p>
<h3 id="from-stdin">From STDIN<a class="headerlink" href="#from-stdin" title="Permanent link">&para;</a></h3>
<p>Use "-" (without quotes) inplace of a file name if you wish to pipe in input from STDIN.</p>
<pre><code class="bash">cat sample.yaml | yq d - b.c
</code></pre>
<h3 id="deleting-nodes-in-place">Deleting nodes in-place<a class="headerlink" href="#deleting-nodes-in-place" title="Permanent link">&para;</a></h3>
<p>Given a sample.yaml file of:</p>
<pre><code class="yaml">b:
c: 2
apples: green
</code></pre>
<p>then</p>
<pre><code class="bash">yq d -i sample.yaml b.c
</code></pre>
<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">&para;</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">&para;</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>
</article>
</div>
</div>
</main>
<footer class="md-footer">
<div class="md-footer-nav">
<nav class="md-footer-nav__inner md-grid">
<a href="../prefix/" title="Prefix" class="md-flex md-footer-nav__link md-footer-nav__link--prev" rel="prev">
<div class="md-flex__cell md-flex__cell--shrink">
<i class="md-icon md-icon--arrow-back md-footer-nav__button"></i>
</div>
<div class="md-flex__cell md-flex__cell--stretch md-footer-nav__title">
<span class="md-flex__ellipsis">
<span class="md-footer-nav__direction">
Previous
</span>
Prefix
</span>
</div>
</a>
<a href="../create/" title="Create" class="md-flex md-footer-nav__link md-footer-nav__link--next" rel="next">
<div class="md-flex__cell md-flex__cell--stretch md-footer-nav__title">
<span class="md-flex__ellipsis">
<span class="md-footer-nav__direction">
Next
</span>
Create
</span>
</div>
<div class="md-flex__cell md-flex__cell--shrink">
<i class="md-icon md-icon--arrow-forward md-footer-nav__button"></i>
</div>
</a>
</nav>
</div>
<div class="md-footer-meta md-typeset">
<div class="md-footer-meta__inner md-grid">
<div class="md-footer-copyright">
powered by
<a href="https://www.mkdocs.org">MkDocs</a>
and
<a href="https://squidfunk.github.io/mkdocs-material/">
Material for MkDocs</a>
</div>
<div class="md-footer-social">
<link rel="stylesheet" href="../assets/fonts/font-awesome.css">
<a href="https://github.com/mikefarah" class="md-footer-social__link fa fa-github"></a>
<a href="https://www.linkedin.com/in/mike-farah-b5a75b2/" class="md-footer-social__link fa fa-linkedin"></a>
</div>
</div>
</div>
</footer>
</div>
<script src="../assets/javascripts/application.39abc4af.js"></script>
<script>app.initialize({version:"1.0.4",url:{base:".."}})</script>
</body>
</html>

View File

@@ -32,7 +32,7 @@
<meta name="lang:search.tokenizer" content="[\s\-]+">
<link rel="shortcut icon" href="assets/images/favicon.png">
<meta name="generator" content="mkdocs-1.0.4, mkdocs-material-4.2.0">
<meta name="generator" content="mkdocs-1.0.4, mkdocs-material-4.6.0">
@@ -40,17 +40,17 @@
<link rel="stylesheet" href="assets/stylesheets/application.750b69bd.css">
<link rel="stylesheet" href="assets/stylesheets/application.1b62728e.css">
<script src="assets/javascripts/modernizr.74668098.js"></script>
<script src="assets/javascripts/modernizr.268332fc.js"></script>
<link href="https://fonts.gstatic.com" rel="preconnect" crossorigin>
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:300,400,400i,700|Roboto+Mono">
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:300,400,400i,700%7CRoboto+Mono&display=fallback">
<style>body,input{font-family:"Roboto","Helvetica Neue",Helvetica,Arial,sans-serif}code,kbd,pre{font-family:"Roboto Mono","Courier New",Courier,monospace}</style>
@@ -69,24 +69,7 @@
<defs>
<svg xmlns="http://www.w3.org/2000/svg" width="416" height="448"
viewBox="0 0 416 448" id="__github">
<path fill="currentColor" d="M160 304q0 10-3.125 20.5t-10.75 19-18.125
8.5-18.125-8.5-10.75-19-3.125-20.5 3.125-20.5 10.75-19 18.125-8.5
18.125 8.5 10.75 19 3.125 20.5zM320 304q0 10-3.125 20.5t-10.75
19-18.125 8.5-18.125-8.5-10.75-19-3.125-20.5 3.125-20.5 10.75-19
18.125-8.5 18.125 8.5 10.75 19 3.125 20.5zM360
304q0-30-17.25-51t-46.75-21q-10.25 0-48.75 5.25-17.75 2.75-39.25
2.75t-39.25-2.75q-38-5.25-48.75-5.25-29.5 0-46.75 21t-17.25 51q0 22 8
38.375t20.25 25.75 30.5 15 35 7.375 37.25 1.75h42q20.5 0
37.25-1.75t35-7.375 30.5-15 20.25-25.75 8-38.375zM416 260q0 51.75-15.25
82.75-9.5 19.25-26.375 33.25t-35.25 21.5-42.5 11.875-42.875 5.5-41.75
1.125q-19.5 0-35.5-0.75t-36.875-3.125-38.125-7.5-34.25-12.875-30.25-20.25-21.5-28.75q-15.5-30.75-15.5-82.75
0-59.25 34-99-6.75-20.5-6.75-42.5 0-29 12.75-54.5 27 0 47.5 9.875t47.25
30.875q36.75-8.75 77.25-8.75 37 0 70 8 26.25-20.5
46.75-30.25t47.25-9.75q12.75 25.5 12.75 54.5 0 21.75-6.75 42 34 40 34
99.5z" />
</svg>
<svg xmlns="http://www.w3.org/2000/svg" width="416" height="448" viewBox="0 0 416 448" id="__github"><path fill="currentColor" d="M160 304q0 10-3.125 20.5t-10.75 19T128 352t-18.125-8.5-10.75-19T96 304t3.125-20.5 10.75-19T128 256t18.125 8.5 10.75 19T160 304zm160 0q0 10-3.125 20.5t-10.75 19T288 352t-18.125-8.5-10.75-19T256 304t3.125-20.5 10.75-19T288 256t18.125 8.5 10.75 19T320 304zm40 0q0-30-17.25-51T296 232q-10.25 0-48.75 5.25Q229.5 240 208 240t-39.25-2.75Q130.75 232 120 232q-29.5 0-46.75 21T56 304q0 22 8 38.375t20.25 25.75 30.5 15 35 7.375 37.25 1.75h42q20.5 0 37.25-1.75t35-7.375 30.5-15 20.25-25.75T360 304zm56-44q0 51.75-15.25 82.75-9.5 19.25-26.375 33.25t-35.25 21.5-42.5 11.875-42.875 5.5T212 416q-19.5 0-35.5-.75t-36.875-3.125-38.125-7.5-34.25-12.875T37 371.5t-21.5-28.75Q0 312 0 260q0-59.25 34-99-6.75-20.5-6.75-42.5 0-29 12.75-54.5 27 0 47.5 9.875t47.25 30.875Q171.5 96 212 96q37 0 70 8 26.25-20.5 46.75-30.25T376 64q12.75 25.5 12.75 54.5 0 21.75-6.75 42 34 40 34 99.5z"/></svg>
</defs>
</svg>
@@ -94,7 +77,7 @@
<input class="md-toggle" data-md-toggle="search" type="checkbox" id="__search" autocomplete="off">
<label class="md-overlay" data-md-component="overlay" for="__drawer"></label>
<a href="#yq" tabindex="1" class="md-skip">
<a href="#new-documentation-website" tabindex="1" class="md-skip">
Skip to content
</a>
@@ -118,9 +101,7 @@
<span class="md-header-nav__topic">
Yq
</span>
<span class="md-header-nav__topic">
Install
</span>
</div>
</div>
@@ -128,28 +109,6 @@
<label class="md-icon md-icon--search md-header-nav__button" for="__search"></label>
<div class="md-search" data-md-component="search" role="dialog">
<label class="md-search__overlay" for="__search"></label>
<div class="md-search__inner" role="search">
<form class="md-search__form" name="search">
<input type="text" class="md-search__input" name="query" placeholder="Search" autocapitalize="off" autocorrect="off" autocomplete="off" spellcheck="false" data-md-component="query" data-md-state="active">
<label class="md-icon md-search__icon" for="__search"></label>
<button type="reset" class="md-icon md-search__icon" data-md-component="reset" tabindex="-1">
&#xE5CD;
</button>
</form>
<div class="md-search__output">
<div class="md-search__scrollwrap" data-md-scrollfix>
<div class="md-search-result" data-md-component="result">
<div class="md-search-result__meta">
Type to start searching
</div>
<ol class="md-search-result__list"></ol>
</div>
</div>
</div>
</div>
</div>
</div>
@@ -184,263 +143,25 @@
<main class="md-main">
<main class="md-main" role="main">
<div class="md-main__inner md-grid" data-md-component="container">
<div class="md-sidebar md-sidebar--primary" data-md-component="navigation">
<div class="md-sidebar__scrollwrap">
<div class="md-sidebar__inner">
<nav class="md-nav md-nav--primary" data-md-level="0">
<label class="md-nav__title md-nav__title--site" for="__drawer">
<a href="." title="Yq" class="md-nav__button md-logo">
<i class="md-icon"></i>
</a>
Yq
</label>
<div class="md-nav__source">
<a href="https://github.com/mikefarah/yq/" title="Go to repository" class="md-source" data-md-source="github">
<div class="md-source__icon">
<svg viewBox="0 0 24 24" width="24" height="24">
<use xlink:href="#__github" width="24" height="24"></use>
</svg>
</div>
<div class="md-source__repository">
mikefarah/yq
</div>
</a>
</div>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item md-nav__item--active">
<input class="md-toggle md-nav__toggle" data-md-toggle="toc" type="checkbox" id="__toc">
<label class="md-nav__link md-nav__link--active" for="__toc">
Install
</label>
<a href="." title="Install" class="md-nav__link md-nav__link--active">
Install
</a>
<nav class="md-nav md-nav--secondary">
<label class="md-nav__title" for="__toc">Table of contents</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="#install" title="Install" class="md-nav__link">
Install
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="read/" title="Read" class="md-nav__link">
Read
</a>
</li>
<li class="md-nav__item">
<a href="path_expressions/" title="Path Expressions" class="md-nav__link">
Path Expressions
</a>
</li>
<li class="md-nav__item">
<a href="write/" title="Write/Update" class="md-nav__link">
Write/Update
</a>
</li>
<li class="md-nav__item">
<a href="prefix/" title="Prefix" class="md-nav__link">
Prefix
</a>
</li>
<li class="md-nav__item">
<a href="delete/" title="Delete" class="md-nav__link">
Delete
</a>
</li>
<li class="md-nav__item">
<a href="create/" title="Create" class="md-nav__link">
Create
</a>
</li>
<li class="md-nav__item">
<a href="convert/" title="Convert" class="md-nav__link">
Convert
</a>
</li>
<li class="md-nav__item">
<a href="merge/" title="Merge" class="md-nav__link">
Merge
</a>
</li>
</ul>
</nav>
</div>
</div>
</div>
<div class="md-sidebar md-sidebar--secondary" data-md-component="toc">
<div class="md-sidebar__scrollwrap">
<div class="md-sidebar__inner">
<nav class="md-nav md-nav--secondary">
<label class="md-nav__title" for="__toc">Table of contents</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="#install" title="Install" class="md-nav__link">
Install
</a>
</li>
</ul>
</nav>
</div>
</div>
</div>
<div class="md-content">
<article class="md-content__inner md-typeset">
<a href="https://github.com/mikefarah/yq/edit/master/docs/index.md" title="Edit this page" class="md-icon md-content__icon">&#xE3C9;</a>
<h1>New documentation website</h1>
<h1 id="yq">yq<a class="headerlink" href="#yq" title="Permanent link">&para;</a></h1>
<p>yq is a lightweight and portable command-line YAML processor</p>
<p>The aim of the project is to be the <a href="https://github.com/stedolan/jq">jq</a> or sed of yaml files.</p>
<h2 id="install">Install<a class="headerlink" href="#install" title="Permanent link">&para;</a></h2>
<p>On MacOS:</p>
<pre><code>brew install yq
</code></pre>
<p>On Ubuntu and other Linux distros supporting <code>snap</code> packages:</p>
<pre><code>snap install yq
</code></pre>
<p>On Ubuntu 16.04 or higher from Debian package:</p>
<pre><code>sudo add-apt-repository ppa:rmescandon/yq
sudo apt update
sudo apt install yq -y
</code></pre>
<p>or, <a href="https://github.com/mikefarah/yq/releases/latest">Download latest binary</a> or alternatively:</p>
<pre><code>GO111MODULE=on go get github.com/mikefarah/yq/v3
</code></pre>
<p><a href="https://github.com/mikefarah/yq">View on GitHub</a></p>
<p>User docs are better than ever, and have been <a href="https://mikefarah.gitbook.io/yq">moved here</a></p>
@@ -455,27 +176,6 @@ sudo apt install yq -y
<footer class="md-footer">
<div class="md-footer-nav">
<nav class="md-footer-nav__inner md-grid">
<a href="read/" title="Read" class="md-flex md-footer-nav__link md-footer-nav__link--next" rel="next">
<div class="md-flex__cell md-flex__cell--stretch md-footer-nav__title">
<span class="md-flex__ellipsis">
<span class="md-footer-nav__direction">
Next
</span>
Read
</span>
</div>
<div class="md-flex__cell md-flex__cell--shrink">
<i class="md-icon md-icon--arrow-forward md-footer-nav__button"></i>
</div>
</a>
</nav>
</div>
<div class="md-footer-meta md-typeset">
<div class="md-footer-meta__inner md-grid">
<div class="md-footer-copyright">
@@ -487,22 +187,13 @@ sudo apt install yq -y
Material for MkDocs</a>
</div>
<div class="md-footer-social">
<link rel="stylesheet" href="assets/fonts/font-awesome.css">
<a href="https://github.com/mikefarah" class="md-footer-social__link fa fa-github"></a>
<a href="https://www.linkedin.com/in/mike-farah-b5a75b2/" class="md-footer-social__link fa fa-linkedin"></a>
</div>
</div>
</div>
</footer>
</div>
<script src="assets/javascripts/application.39abc4af.js"></script>
<script src="assets/javascripts/application.808e90bb.js"></script>
<script>app.initialize({version:"1.0.4",url:{base:"."}})</script>

View File

@@ -1,741 +0,0 @@
<!doctype html>
<html lang="en" class="no-js">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta http-equiv="x-ua-compatible" content="ie=edge">
<meta name="lang:clipboard.copy" content="Copy to clipboard">
<meta name="lang:clipboard.copied" content="Copied to clipboard">
<meta name="lang:search.language" content="en">
<meta name="lang:search.pipeline.stopwords" content="True">
<meta name="lang:search.pipeline.trimmer" content="True">
<meta name="lang:search.result.none" content="No matching documents">
<meta name="lang:search.result.one" content="1 matching document">
<meta name="lang:search.result.other" content="# matching documents">
<meta name="lang:search.tokenizer" content="[\s\-]+">
<link rel="shortcut icon" href="../assets/images/favicon.png">
<meta name="generator" content="mkdocs-1.0.4, mkdocs-material-4.2.0">
<title>Merge - Yq</title>
<link rel="stylesheet" href="../assets/stylesheets/application.750b69bd.css">
<script src="../assets/javascripts/modernizr.74668098.js"></script>
<link href="https://fonts.gstatic.com" rel="preconnect" crossorigin>
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:300,400,400i,700|Roboto+Mono">
<style>body,input{font-family:"Roboto","Helvetica Neue",Helvetica,Arial,sans-serif}code,kbd,pre{font-family:"Roboto Mono","Courier New",Courier,monospace}</style>
<link rel="stylesheet" href="../assets/fonts/material-icons.css">
</head>
<body dir="ltr">
<svg class="md-svg">
<defs>
<svg xmlns="http://www.w3.org/2000/svg" width="416" height="448"
viewBox="0 0 416 448" id="__github">
<path fill="currentColor" d="M160 304q0 10-3.125 20.5t-10.75 19-18.125
8.5-18.125-8.5-10.75-19-3.125-20.5 3.125-20.5 10.75-19 18.125-8.5
18.125 8.5 10.75 19 3.125 20.5zM320 304q0 10-3.125 20.5t-10.75
19-18.125 8.5-18.125-8.5-10.75-19-3.125-20.5 3.125-20.5 10.75-19
18.125-8.5 18.125 8.5 10.75 19 3.125 20.5zM360
304q0-30-17.25-51t-46.75-21q-10.25 0-48.75 5.25-17.75 2.75-39.25
2.75t-39.25-2.75q-38-5.25-48.75-5.25-29.5 0-46.75 21t-17.25 51q0 22 8
38.375t20.25 25.75 30.5 15 35 7.375 37.25 1.75h42q20.5 0
37.25-1.75t35-7.375 30.5-15 20.25-25.75 8-38.375zM416 260q0 51.75-15.25
82.75-9.5 19.25-26.375 33.25t-35.25 21.5-42.5 11.875-42.875 5.5-41.75
1.125q-19.5 0-35.5-0.75t-36.875-3.125-38.125-7.5-34.25-12.875-30.25-20.25-21.5-28.75q-15.5-30.75-15.5-82.75
0-59.25 34-99-6.75-20.5-6.75-42.5 0-29 12.75-54.5 27 0 47.5 9.875t47.25
30.875q36.75-8.75 77.25-8.75 37 0 70 8 26.25-20.5
46.75-30.25t47.25-9.75q12.75 25.5 12.75 54.5 0 21.75-6.75 42 34 40 34
99.5z" />
</svg>
</defs>
</svg>
<input class="md-toggle" data-md-toggle="drawer" type="checkbox" id="__drawer" autocomplete="off">
<input class="md-toggle" data-md-toggle="search" type="checkbox" id="__search" autocomplete="off">
<label class="md-overlay" data-md-component="overlay" for="__drawer"></label>
<a href="#to-stdout" tabindex="1" class="md-skip">
Skip to content
</a>
<header class="md-header" data-md-component="header">
<nav class="md-header-nav md-grid">
<div class="md-flex">
<div class="md-flex__cell md-flex__cell--shrink">
<a href=".." title="Yq" class="md-header-nav__button md-logo">
<i class="md-icon"></i>
</a>
</div>
<div class="md-flex__cell md-flex__cell--shrink">
<label class="md-icon md-icon--menu md-header-nav__button" for="__drawer"></label>
</div>
<div class="md-flex__cell md-flex__cell--stretch">
<div class="md-flex__ellipsis md-header-nav__title" data-md-component="title">
<span class="md-header-nav__topic">
Yq
</span>
<span class="md-header-nav__topic">
Merge
</span>
</div>
</div>
<div class="md-flex__cell md-flex__cell--shrink">
<label class="md-icon md-icon--search md-header-nav__button" for="__search"></label>
<div class="md-search" data-md-component="search" role="dialog">
<label class="md-search__overlay" for="__search"></label>
<div class="md-search__inner" role="search">
<form class="md-search__form" name="search">
<input type="text" class="md-search__input" name="query" placeholder="Search" autocapitalize="off" autocorrect="off" autocomplete="off" spellcheck="false" data-md-component="query" data-md-state="active">
<label class="md-icon md-search__icon" for="__search"></label>
<button type="reset" class="md-icon md-search__icon" data-md-component="reset" tabindex="-1">
&#xE5CD;
</button>
</form>
<div class="md-search__output">
<div class="md-search__scrollwrap" data-md-scrollfix>
<div class="md-search-result" data-md-component="result">
<div class="md-search-result__meta">
Type to start searching
</div>
<ol class="md-search-result__list"></ol>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="md-flex__cell md-flex__cell--shrink">
<div class="md-header-nav__source">
<a href="https://github.com/mikefarah/yq/" title="Go to repository" class="md-source" data-md-source="github">
<div class="md-source__icon">
<svg viewBox="0 0 24 24" width="24" height="24">
<use xlink:href="#__github" width="24" height="24"></use>
</svg>
</div>
<div class="md-source__repository">
mikefarah/yq
</div>
</a>
</div>
</div>
</div>
</nav>
</header>
<div class="md-container">
<main class="md-main">
<div class="md-main__inner md-grid" data-md-component="container">
<div class="md-sidebar md-sidebar--primary" data-md-component="navigation">
<div class="md-sidebar__scrollwrap">
<div class="md-sidebar__inner">
<nav class="md-nav md-nav--primary" data-md-level="0">
<label class="md-nav__title md-nav__title--site" for="__drawer">
<a href=".." title="Yq" class="md-nav__button md-logo">
<i class="md-icon"></i>
</a>
Yq
</label>
<div class="md-nav__source">
<a href="https://github.com/mikefarah/yq/" title="Go to repository" class="md-source" data-md-source="github">
<div class="md-source__icon">
<svg viewBox="0 0 24 24" width="24" height="24">
<use xlink:href="#__github" width="24" height="24"></use>
</svg>
</div>
<div class="md-source__repository">
mikefarah/yq
</div>
</a>
</div>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href=".." title="Install" class="md-nav__link">
Install
</a>
</li>
<li class="md-nav__item">
<a href="../read/" title="Read" class="md-nav__link">
Read
</a>
</li>
<li class="md-nav__item">
<a href="../path_expressions/" title="Path Expressions" class="md-nav__link">
Path Expressions
</a>
</li>
<li class="md-nav__item">
<a href="../write/" title="Write/Update" class="md-nav__link">
Write/Update
</a>
</li>
<li class="md-nav__item">
<a href="../prefix/" title="Prefix" class="md-nav__link">
Prefix
</a>
</li>
<li class="md-nav__item">
<a href="../delete/" title="Delete" class="md-nav__link">
Delete
</a>
</li>
<li class="md-nav__item">
<a href="../create/" title="Create" class="md-nav__link">
Create
</a>
</li>
<li class="md-nav__item">
<a href="../convert/" title="Convert" class="md-nav__link">
Convert
</a>
</li>
<li class="md-nav__item md-nav__item--active">
<input class="md-toggle md-nav__toggle" data-md-toggle="toc" type="checkbox" id="__toc">
<label class="md-nav__link md-nav__link--active" for="__toc">
Merge
</label>
<a href="./" title="Merge" class="md-nav__link md-nav__link--active">
Merge
</a>
<nav class="md-nav md-nav--secondary">
<label class="md-nav__title" for="__toc">Table of contents</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="#to-stdout" title="To Stdout" class="md-nav__link">
To Stdout
</a>
</li>
<li class="md-nav__item">
<a href="#updating-files-in-place" title="Updating files in-place" class="md-nav__link">
Updating files in-place
</a>
</li>
<li class="md-nav__item">
<a href="#overwrite-values" title="Overwrite values" class="md-nav__link">
Overwrite values
</a>
</li>
<li class="md-nav__item">
<a href="#overwrite-values-with-arrays" title="Overwrite values with arrays" class="md-nav__link">
Overwrite values with arrays
</a>
</li>
<li class="md-nav__item">
<a href="#append-values-with-arrays" title="Append values with arrays" class="md-nav__link">
Append values with arrays
</a>
</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>
</nav>
</li>
</ul>
</nav>
</div>
</div>
</div>
<div class="md-sidebar md-sidebar--secondary" data-md-component="toc">
<div class="md-sidebar__scrollwrap">
<div class="md-sidebar__inner">
<nav class="md-nav md-nav--secondary">
<label class="md-nav__title" for="__toc">Table of contents</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="#to-stdout" title="To Stdout" class="md-nav__link">
To Stdout
</a>
</li>
<li class="md-nav__item">
<a href="#updating-files-in-place" title="Updating files in-place" class="md-nav__link">
Updating files in-place
</a>
</li>
<li class="md-nav__item">
<a href="#overwrite-values" title="Overwrite values" class="md-nav__link">
Overwrite values
</a>
</li>
<li class="md-nav__item">
<a href="#overwrite-values-with-arrays" title="Overwrite values with arrays" class="md-nav__link">
Overwrite values with arrays
</a>
</li>
<li class="md-nav__item">
<a href="#append-values-with-arrays" title="Append values with arrays" class="md-nav__link">
Append values with arrays
</a>
</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>
</nav>
</div>
</div>
</div>
<div class="md-content">
<article class="md-content__inner md-typeset">
<a href="https://github.com/mikefarah/yq/edit/master/docs/merge.md" title="Edit this page" class="md-icon md-content__icon">&#xE3C9;</a>
<h1>Merge</h1>
<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>
<pre><code>yq m &lt;yaml_file&gt; &lt;path&gt;...
</code></pre>
<h3 id="to-stdout">To Stdout<a class="headerlink" href="#to-stdout" title="Permanent link">&para;</a></h3>
<p>Given a data1.yaml file of:</p>
<pre><code class="yaml">a: simple
b: [1, 2]
</code></pre>
<p>and data2.yaml file of:</p>
<pre><code class="yaml">a: other
c:
test: 1
</code></pre>
<p>then</p>
<pre><code class="bash">yq m data1.yaml data2.yaml
</code></pre>
<p>will output:</p>
<pre><code class="yaml">a: simple
b: [1, 2]
c:
test: 1
</code></pre>
<h3 id="updating-files-in-place">Updating files in-place<a class="headerlink" href="#updating-files-in-place" title="Permanent link">&para;</a></h3>
<p>Given a data1.yaml file of:</p>
<pre><code class="yaml">a: simple
b: [1, 2]
</code></pre>
<p>and data2.yaml file of:</p>
<pre><code class="yaml">a: other
c:
test: 1
</code></pre>
<p>then</p>
<pre><code class="bash">yq m -i data1.yaml data2.yaml
</code></pre>
<p>will update the data1.yaml file so that the value of 'c' is 'test: 1'.</p>
<h3 id="overwrite-values">Overwrite values<a class="headerlink" href="#overwrite-values" title="Permanent link">&para;</a></h3>
<p>Given a data1.yaml file of:</p>
<pre><code class="yaml">a: simple
b: [1, 2]
</code></pre>
<p>and data2.yaml file of:</p>
<pre><code class="yaml">a: other
c:
test: 1
</code></pre>
<p>then</p>
<pre><code class="bash">yq m -x data1.yaml data2.yaml
</code></pre>
<p>will output:</p>
<pre><code class="yaml">a: other
b: [1, 2]
c:
test: 1
</code></pre>
<h3 id="overwrite-values-with-arrays">Overwrite values with arrays<a class="headerlink" href="#overwrite-values-with-arrays" title="Permanent link">&para;</a></h3>
<p>Given a data1.yaml file of:</p>
<pre><code class="yaml">a: simple
b: [1, 2]
</code></pre>
<p>and data3.yaml file of:</p>
<pre><code class="yaml">b: [3, 4]
c:
test: 2
other: true
d: false
</code></pre>
<p>then</p>
<pre><code class="bash">yq m -x data1.yaml data3.yaml
</code></pre>
<p>will output:</p>
<pre><code class="yaml">a: simple
b: [3, 4]
c:
test: 2
other: true
d: false
</code></pre>
<p>Notice that 'b' does not result in the merging of the values within an array. </p>
<h3 id="append-values-with-arrays">Append values with arrays<a class="headerlink" href="#append-values-with-arrays" title="Permanent link">&para;</a></h3>
<p>Given a data1.yaml file of:</p>
<pre><code class="yaml">a: simple
b: [1, 2]
d: hi
</code></pre>
<p>and data3.yaml file of:</p>
<pre><code class="yaml">a: something
b: [3, 4]
c:
test: 2
other: true
</code></pre>
<p>then</p>
<pre><code class="bash">yq m -a data1.yaml data3.yaml
</code></pre>
<p>will output:</p>
<pre><code class="yaml">a: simple
b: [1, 2, 3, 4]
c:
test: 2
other: true
d: hi
</code></pre>
<p>Note that the 'b' array has concatenated the values from the second data file. Also note that other map keys are not overridden (field a).</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">&para;</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">&para;</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>
</article>
</div>
</div>
</main>
<footer class="md-footer">
<div class="md-footer-nav">
<nav class="md-footer-nav__inner md-grid">
<a href="../convert/" title="Convert" class="md-flex md-footer-nav__link md-footer-nav__link--prev" rel="prev">
<div class="md-flex__cell md-flex__cell--shrink">
<i class="md-icon md-icon--arrow-back md-footer-nav__button"></i>
</div>
<div class="md-flex__cell md-flex__cell--stretch md-footer-nav__title">
<span class="md-flex__ellipsis">
<span class="md-footer-nav__direction">
Previous
</span>
Convert
</span>
</div>
</a>
</nav>
</div>
<div class="md-footer-meta md-typeset">
<div class="md-footer-meta__inner md-grid">
<div class="md-footer-copyright">
powered by
<a href="https://www.mkdocs.org">MkDocs</a>
and
<a href="https://squidfunk.github.io/mkdocs-material/">
Material for MkDocs</a>
</div>
<div class="md-footer-social">
<link rel="stylesheet" href="../assets/fonts/font-awesome.css">
<a href="https://github.com/mikefarah" class="md-footer-social__link fa fa-github"></a>
<a href="https://www.linkedin.com/in/mike-farah-b5a75b2/" class="md-footer-social__link fa fa-linkedin"></a>
</div>
</div>
</div>
</footer>
</div>
<script src="../assets/javascripts/application.39abc4af.js"></script>
<script>app.initialize({version:"1.0.4",url:{base:".."}})</script>
</body>
</html>

View File

@@ -1,862 +0,0 @@
<!doctype html>
<html lang="en" class="no-js">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta http-equiv="x-ua-compatible" content="ie=edge">
<meta name="lang:clipboard.copy" content="Copy to clipboard">
<meta name="lang:clipboard.copied" content="Copied to clipboard">
<meta name="lang:search.language" content="en">
<meta name="lang:search.pipeline.stopwords" content="True">
<meta name="lang:search.pipeline.trimmer" content="True">
<meta name="lang:search.result.none" content="No matching documents">
<meta name="lang:search.result.one" content="1 matching document">
<meta name="lang:search.result.other" content="# matching documents">
<meta name="lang:search.tokenizer" content="[\s\-]+">
<link rel="shortcut icon" href="../assets/images/favicon.png">
<meta name="generator" content="mkdocs-1.0.4, mkdocs-material-4.2.0">
<title>Path Expressions - Yq</title>
<link rel="stylesheet" href="../assets/stylesheets/application.750b69bd.css">
<script src="../assets/javascripts/modernizr.74668098.js"></script>
<link href="https://fonts.gstatic.com" rel="preconnect" crossorigin>
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:300,400,400i,700|Roboto+Mono">
<style>body,input{font-family:"Roboto","Helvetica Neue",Helvetica,Arial,sans-serif}code,kbd,pre{font-family:"Roboto Mono","Courier New",Courier,monospace}</style>
<link rel="stylesheet" href="../assets/fonts/material-icons.css">
</head>
<body dir="ltr">
<svg class="md-svg">
<defs>
<svg xmlns="http://www.w3.org/2000/svg" width="416" height="448"
viewBox="0 0 416 448" id="__github">
<path fill="currentColor" d="M160 304q0 10-3.125 20.5t-10.75 19-18.125
8.5-18.125-8.5-10.75-19-3.125-20.5 3.125-20.5 10.75-19 18.125-8.5
18.125 8.5 10.75 19 3.125 20.5zM320 304q0 10-3.125 20.5t-10.75
19-18.125 8.5-18.125-8.5-10.75-19-3.125-20.5 3.125-20.5 10.75-19
18.125-8.5 18.125 8.5 10.75 19 3.125 20.5zM360
304q0-30-17.25-51t-46.75-21q-10.25 0-48.75 5.25-17.75 2.75-39.25
2.75t-39.25-2.75q-38-5.25-48.75-5.25-29.5 0-46.75 21t-17.25 51q0 22 8
38.375t20.25 25.75 30.5 15 35 7.375 37.25 1.75h42q20.5 0
37.25-1.75t35-7.375 30.5-15 20.25-25.75 8-38.375zM416 260q0 51.75-15.25
82.75-9.5 19.25-26.375 33.25t-35.25 21.5-42.5 11.875-42.875 5.5-41.75
1.125q-19.5 0-35.5-0.75t-36.875-3.125-38.125-7.5-34.25-12.875-30.25-20.25-21.5-28.75q-15.5-30.75-15.5-82.75
0-59.25 34-99-6.75-20.5-6.75-42.5 0-29 12.75-54.5 27 0 47.5 9.875t47.25
30.875q36.75-8.75 77.25-8.75 37 0 70 8 26.25-20.5
46.75-30.25t47.25-9.75q12.75 25.5 12.75 54.5 0 21.75-6.75 42 34 40 34
99.5z" />
</svg>
</defs>
</svg>
<input class="md-toggle" data-md-toggle="drawer" type="checkbox" id="__drawer" autocomplete="off">
<input class="md-toggle" data-md-toggle="search" type="checkbox" id="__search" autocomplete="off">
<label class="md-overlay" data-md-component="overlay" for="__drawer"></label>
<a href="#simple-expressions" tabindex="1" class="md-skip">
Skip to content
</a>
<header class="md-header" data-md-component="header">
<nav class="md-header-nav md-grid">
<div class="md-flex">
<div class="md-flex__cell md-flex__cell--shrink">
<a href=".." title="Yq" class="md-header-nav__button md-logo">
<i class="md-icon"></i>
</a>
</div>
<div class="md-flex__cell md-flex__cell--shrink">
<label class="md-icon md-icon--menu md-header-nav__button" for="__drawer"></label>
</div>
<div class="md-flex__cell md-flex__cell--stretch">
<div class="md-flex__ellipsis md-header-nav__title" data-md-component="title">
<span class="md-header-nav__topic">
Yq
</span>
<span class="md-header-nav__topic">
Path Expressions
</span>
</div>
</div>
<div class="md-flex__cell md-flex__cell--shrink">
<label class="md-icon md-icon--search md-header-nav__button" for="__search"></label>
<div class="md-search" data-md-component="search" role="dialog">
<label class="md-search__overlay" for="__search"></label>
<div class="md-search__inner" role="search">
<form class="md-search__form" name="search">
<input type="text" class="md-search__input" name="query" placeholder="Search" autocapitalize="off" autocorrect="off" autocomplete="off" spellcheck="false" data-md-component="query" data-md-state="active">
<label class="md-icon md-search__icon" for="__search"></label>
<button type="reset" class="md-icon md-search__icon" data-md-component="reset" tabindex="-1">
&#xE5CD;
</button>
</form>
<div class="md-search__output">
<div class="md-search__scrollwrap" data-md-scrollfix>
<div class="md-search-result" data-md-component="result">
<div class="md-search-result__meta">
Type to start searching
</div>
<ol class="md-search-result__list"></ol>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="md-flex__cell md-flex__cell--shrink">
<div class="md-header-nav__source">
<a href="https://github.com/mikefarah/yq/" title="Go to repository" class="md-source" data-md-source="github">
<div class="md-source__icon">
<svg viewBox="0 0 24 24" width="24" height="24">
<use xlink:href="#__github" width="24" height="24"></use>
</svg>
</div>
<div class="md-source__repository">
mikefarah/yq
</div>
</a>
</div>
</div>
</div>
</nav>
</header>
<div class="md-container">
<main class="md-main">
<div class="md-main__inner md-grid" data-md-component="container">
<div class="md-sidebar md-sidebar--primary" data-md-component="navigation">
<div class="md-sidebar__scrollwrap">
<div class="md-sidebar__inner">
<nav class="md-nav md-nav--primary" data-md-level="0">
<label class="md-nav__title md-nav__title--site" for="__drawer">
<a href=".." title="Yq" class="md-nav__button md-logo">
<i class="md-icon"></i>
</a>
Yq
</label>
<div class="md-nav__source">
<a href="https://github.com/mikefarah/yq/" title="Go to repository" class="md-source" data-md-source="github">
<div class="md-source__icon">
<svg viewBox="0 0 24 24" width="24" height="24">
<use xlink:href="#__github" width="24" height="24"></use>
</svg>
</div>
<div class="md-source__repository">
mikefarah/yq
</div>
</a>
</div>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href=".." title="Install" class="md-nav__link">
Install
</a>
</li>
<li class="md-nav__item">
<a href="../read/" title="Read" class="md-nav__link">
Read
</a>
</li>
<li class="md-nav__item md-nav__item--active">
<input class="md-toggle md-nav__toggle" data-md-toggle="toc" type="checkbox" id="__toc">
<label class="md-nav__link md-nav__link--active" for="__toc">
Path Expressions
</label>
<a href="./" title="Path Expressions" class="md-nav__link md-nav__link--active">
Path Expressions
</a>
<nav class="md-nav md-nav--secondary">
<label class="md-nav__title" for="__toc">Table of contents</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="#simple-expressions" title="Simple expressions" class="md-nav__link">
Simple expressions
</a>
<nav class="md-nav">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#maps" title="Maps" class="md-nav__link">
Maps
</a>
</li>
<li class="md-nav__item">
<a href="#arrays" title="Arrays" class="md-nav__link">
Arrays
</a>
<nav class="md-nav">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#appending-to-arrays" title="Appending to arrays" class="md-nav__link">
Appending to arrays
</a>
</li>
</ul>
</nav>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="#splat" title="Splat" class="md-nav__link">
Splat
</a>
<nav class="md-nav">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#maps_1" title="Maps" class="md-nav__link">
Maps
</a>
</li>
<li class="md-nav__item">
<a href="#arrays_1" title="Arrays" class="md-nav__link">
Arrays
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="#deep-splat" title="Deep Splat" class="md-nav__link">
Deep Splat
</a>
</li>
<li class="md-nav__item">
<a href="#finding-parents-with-particular-children-nodes" title="Finding parents with particular children nodes" class="md-nav__link">
Finding parents with particular children nodes
</a>
<nav class="md-nav">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#with-prefixes" title="With prefixes" class="md-nav__link">
With prefixes
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="#special-characters" title="Special Characters" class="md-nav__link">
Special Characters
</a>
<nav class="md-nav">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#keys-with-dots" title="Keys with dots" class="md-nav__link">
Keys with dots
</a>
</li>
<li class="md-nav__item">
<a href="#keys-and-values-with-leading-dashes" title="Keys (and values) with leading dashes" class="md-nav__link">
Keys (and values) with leading dashes
</a>
</li>
</ul>
</nav>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="../write/" title="Write/Update" class="md-nav__link">
Write/Update
</a>
</li>
<li class="md-nav__item">
<a href="../prefix/" title="Prefix" class="md-nav__link">
Prefix
</a>
</li>
<li class="md-nav__item">
<a href="../delete/" title="Delete" class="md-nav__link">
Delete
</a>
</li>
<li class="md-nav__item">
<a href="../create/" title="Create" class="md-nav__link">
Create
</a>
</li>
<li class="md-nav__item">
<a href="../convert/" title="Convert" class="md-nav__link">
Convert
</a>
</li>
<li class="md-nav__item">
<a href="../merge/" title="Merge" class="md-nav__link">
Merge
</a>
</li>
</ul>
</nav>
</div>
</div>
</div>
<div class="md-sidebar md-sidebar--secondary" data-md-component="toc">
<div class="md-sidebar__scrollwrap">
<div class="md-sidebar__inner">
<nav class="md-nav md-nav--secondary">
<label class="md-nav__title" for="__toc">Table of contents</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="#simple-expressions" title="Simple expressions" class="md-nav__link">
Simple expressions
</a>
<nav class="md-nav">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#maps" title="Maps" class="md-nav__link">
Maps
</a>
</li>
<li class="md-nav__item">
<a href="#arrays" title="Arrays" class="md-nav__link">
Arrays
</a>
<nav class="md-nav">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#appending-to-arrays" title="Appending to arrays" class="md-nav__link">
Appending to arrays
</a>
</li>
</ul>
</nav>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="#splat" title="Splat" class="md-nav__link">
Splat
</a>
<nav class="md-nav">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#maps_1" title="Maps" class="md-nav__link">
Maps
</a>
</li>
<li class="md-nav__item">
<a href="#arrays_1" title="Arrays" class="md-nav__link">
Arrays
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="#deep-splat" title="Deep Splat" class="md-nav__link">
Deep Splat
</a>
</li>
<li class="md-nav__item">
<a href="#finding-parents-with-particular-children-nodes" title="Finding parents with particular children nodes" class="md-nav__link">
Finding parents with particular children nodes
</a>
<nav class="md-nav">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#with-prefixes" title="With prefixes" class="md-nav__link">
With prefixes
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="#special-characters" title="Special Characters" class="md-nav__link">
Special Characters
</a>
<nav class="md-nav">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#keys-with-dots" title="Keys with dots" class="md-nav__link">
Keys with dots
</a>
</li>
<li class="md-nav__item">
<a href="#keys-and-values-with-leading-dashes" title="Keys (and values) with leading dashes" class="md-nav__link">
Keys (and values) with leading dashes
</a>
</li>
</ul>
</nav>
</li>
</ul>
</nav>
</div>
</div>
</div>
<div class="md-content">
<article class="md-content__inner md-typeset">
<a href="https://github.com/mikefarah/yq/edit/master/docs/path_expressions.md" title="Edit this page" class="md-icon md-content__icon">&#xE3C9;</a>
<h1>Path Expressions</h1>
<p>Path expressions are used to deeply navigate and match particular yaml nodes.</p>
<p><em>As a general rule, you should wrap paths in quotes in the CLI to prevent your interpreter from processing '*, []' and other special characters.</em></p>
<h2 id="simple-expressions">Simple expressions<a class="headerlink" href="#simple-expressions" title="Permanent link">&para;</a></h2>
<h3 id="maps">Maps<a class="headerlink" href="#maps" title="Permanent link">&para;</a></h3>
<p>a.b.c</p>
<pre><code class="yaml">a:
b:
c: thing # MATCHES
</code></pre>
<h3 id="arrays">Arrays<a class="headerlink" href="#arrays" title="Permanent link">&para;</a></h3>
<p>a.b[1].c</p>
<pre><code class="yaml">a:
b:
- c: thing0
- c: thing1 # MATCHES
- c: thing2
</code></pre>
<h4 id="appending-to-arrays">Appending to arrays<a class="headerlink" href="#appending-to-arrays" title="Permanent link">&para;</a></h4>
<p>(e.g. when using the write command)</p>
<p>a.b[+].c</p>
<pre><code class="yaml">a:
b:
- c: thing0
</code></pre>
<p>Will add a new entry:</p>
<pre><code class="yaml">a:
b:
- c: thing0
- c: thing1 # NEW entry from [+] on B array.
</code></pre>
<h2 id="splat">Splat<a class="headerlink" href="#splat" title="Permanent link">&para;</a></h2>
<h3 id="maps_1">Maps<a class="headerlink" href="#maps_1" title="Permanent link">&para;</a></h3>
<p>a.*.c</p>
<pre><code class="yaml">a:
b1:
c: thing # MATCHES
b2:
c: thing # MATCHES
</code></pre>
<h3 id="arrays_1">Arrays<a class="headerlink" href="#arrays_1" title="Permanent link">&para;</a></h3>
<p>a.b[*].c</p>
<pre><code class="yaml">a:
b:
- c: thing0 # MATCHES
- c: thing1 # MATCHES
- c: thing2 # MATCHES
</code></pre>
<h2 id="deep-splat">Deep Splat<a class="headerlink" href="#deep-splat" title="Permanent link">&para;</a></h2>
<p>'**' will match arbitrary nodes for both maps and arrays:</p>
<p>a.**.c</p>
<pre><code class="yaml">a:
b1:
c: thing1 # MATCHES
b2:
c: thing2 # MATCHES
b3:
d:
- f:
c: thing3 # MATCHES
- f:
g:
c: thing4 # MATCHES
</code></pre>
<h2 id="finding-parents-with-particular-children-nodes">Finding parents with particular children nodes<a class="headerlink" href="#finding-parents-with-particular-children-nodes" title="Permanent link">&para;</a></h2>
<p>a.(b.d==cat).b.c</p>
<pre><code class="yaml">a:
- b:
c: thing0
d: leopard
ba: fast
- b:
c: thing1 # MATCHES
d: cat
ba: meowy
- b:
c: thing2
d: caterpillar
ba: icky
- b:
c: thing3 # MATCHES
d: cat
ba: also meowy
</code></pre>
<h3 id="with-prefixes">With prefixes<a class="headerlink" href="#with-prefixes" title="Permanent link">&para;</a></h3>
<p>a.(b.d==cat*).c</p>
<pre><code class="yaml">a:
- b:
c: thing0
d: leopard
ba: fast
- b:
c: thing1 # MATCHES
d: cat
ba: meowy
- b:
c: thing2 # MATCHES
d: caterpillar
ba: icky
- b:
c: thing3 # MATCHES
d: cat
ba: also meowy
</code></pre>
<h2 id="special-characters">Special Characters<a class="headerlink" href="#special-characters" title="Permanent link">&para;</a></h2>
<h3 id="keys-with-dots">Keys with dots<a class="headerlink" href="#keys-with-dots" title="Permanent link">&para;</a></h3>
<p>When specifying a key that has a dot use key lookup indicator.</p>
<pre><code class="yaml">b:
foo.bar: 7
</code></pre>
<pre><code class="bash">yaml r sample.yaml 'b[foo.bar]'
</code></pre>
<pre><code class="bash">yaml w sample.yaml 'b[foo.bar]' 9
</code></pre>
<p>Any valid yaml key can be specified as part of a key lookup.</p>
<p>Note that the path is in quotes to avoid the square brackets being interpreted by your shell.</p>
<h3 id="keys-and-values-with-leading-dashes">Keys (and values) with leading dashes<a class="headerlink" href="#keys-and-values-with-leading-dashes" title="Permanent link">&para;</a></h3>
<p>If a key or value has leading dashes, yq won't know that you are passing a value as opposed to a flag (and you will get a 'bad flag syntax' error).</p>
<p>To fix that, you will need to tell it to stop processing flags by adding '--' after the last flag like so:</p>
<pre><code class="bash">yq n -t -- --key --value
</code></pre>
<p>Will result in</p>
<pre><code>--key: --value
</code></pre>
</article>
</div>
</div>
</main>
<footer class="md-footer">
<div class="md-footer-nav">
<nav class="md-footer-nav__inner md-grid">
<a href="../read/" title="Read" class="md-flex md-footer-nav__link md-footer-nav__link--prev" rel="prev">
<div class="md-flex__cell md-flex__cell--shrink">
<i class="md-icon md-icon--arrow-back md-footer-nav__button"></i>
</div>
<div class="md-flex__cell md-flex__cell--stretch md-footer-nav__title">
<span class="md-flex__ellipsis">
<span class="md-footer-nav__direction">
Previous
</span>
Read
</span>
</div>
</a>
<a href="../write/" title="Write/Update" class="md-flex md-footer-nav__link md-footer-nav__link--next" rel="next">
<div class="md-flex__cell md-flex__cell--stretch md-footer-nav__title">
<span class="md-flex__ellipsis">
<span class="md-footer-nav__direction">
Next
</span>
Write/Update
</span>
</div>
<div class="md-flex__cell md-flex__cell--shrink">
<i class="md-icon md-icon--arrow-forward md-footer-nav__button"></i>
</div>
</a>
</nav>
</div>
<div class="md-footer-meta md-typeset">
<div class="md-footer-meta__inner md-grid">
<div class="md-footer-copyright">
powered by
<a href="https://www.mkdocs.org">MkDocs</a>
and
<a href="https://squidfunk.github.io/mkdocs-material/">
Material for MkDocs</a>
</div>
<div class="md-footer-social">
<link rel="stylesheet" href="../assets/fonts/font-awesome.css">
<a href="https://github.com/mikefarah" class="md-footer-social__link fa fa-github"></a>
<a href="https://www.linkedin.com/in/mike-farah-b5a75b2/" class="md-footer-social__link fa fa-linkedin"></a>
</div>
</div>
</div>
</footer>
</div>
<script src="../assets/javascripts/application.39abc4af.js"></script>
<script>app.initialize({version:"1.0.4",url:{base:".."}})</script>
</body>
</html>

View File

@@ -1,643 +0,0 @@
<!doctype html>
<html lang="en" class="no-js">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta http-equiv="x-ua-compatible" content="ie=edge">
<meta name="lang:clipboard.copy" content="Copy to clipboard">
<meta name="lang:clipboard.copied" content="Copied to clipboard">
<meta name="lang:search.language" content="en">
<meta name="lang:search.pipeline.stopwords" content="True">
<meta name="lang:search.pipeline.trimmer" content="True">
<meta name="lang:search.result.none" content="No matching documents">
<meta name="lang:search.result.one" content="1 matching document">
<meta name="lang:search.result.other" content="# matching documents">
<meta name="lang:search.tokenizer" content="[\s\-]+">
<link rel="shortcut icon" href="../assets/images/favicon.png">
<meta name="generator" content="mkdocs-1.0.4, mkdocs-material-4.2.0">
<title>Prefix - Yq</title>
<link rel="stylesheet" href="../assets/stylesheets/application.750b69bd.css">
<script src="../assets/javascripts/modernizr.74668098.js"></script>
<link href="https://fonts.gstatic.com" rel="preconnect" crossorigin>
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:300,400,400i,700|Roboto+Mono">
<style>body,input{font-family:"Roboto","Helvetica Neue",Helvetica,Arial,sans-serif}code,kbd,pre{font-family:"Roboto Mono","Courier New",Courier,monospace}</style>
<link rel="stylesheet" href="../assets/fonts/material-icons.css">
</head>
<body dir="ltr">
<svg class="md-svg">
<defs>
<svg xmlns="http://www.w3.org/2000/svg" width="416" height="448"
viewBox="0 0 416 448" id="__github">
<path fill="currentColor" d="M160 304q0 10-3.125 20.5t-10.75 19-18.125
8.5-18.125-8.5-10.75-19-3.125-20.5 3.125-20.5 10.75-19 18.125-8.5
18.125 8.5 10.75 19 3.125 20.5zM320 304q0 10-3.125 20.5t-10.75
19-18.125 8.5-18.125-8.5-10.75-19-3.125-20.5 3.125-20.5 10.75-19
18.125-8.5 18.125 8.5 10.75 19 3.125 20.5zM360
304q0-30-17.25-51t-46.75-21q-10.25 0-48.75 5.25-17.75 2.75-39.25
2.75t-39.25-2.75q-38-5.25-48.75-5.25-29.5 0-46.75 21t-17.25 51q0 22 8
38.375t20.25 25.75 30.5 15 35 7.375 37.25 1.75h42q20.5 0
37.25-1.75t35-7.375 30.5-15 20.25-25.75 8-38.375zM416 260q0 51.75-15.25
82.75-9.5 19.25-26.375 33.25t-35.25 21.5-42.5 11.875-42.875 5.5-41.75
1.125q-19.5 0-35.5-0.75t-36.875-3.125-38.125-7.5-34.25-12.875-30.25-20.25-21.5-28.75q-15.5-30.75-15.5-82.75
0-59.25 34-99-6.75-20.5-6.75-42.5 0-29 12.75-54.5 27 0 47.5 9.875t47.25
30.875q36.75-8.75 77.25-8.75 37 0 70 8 26.25-20.5
46.75-30.25t47.25-9.75q12.75 25.5 12.75 54.5 0 21.75-6.75 42 34 40 34
99.5z" />
</svg>
</defs>
</svg>
<input class="md-toggle" data-md-toggle="drawer" type="checkbox" id="__drawer" autocomplete="off">
<input class="md-toggle" data-md-toggle="search" type="checkbox" id="__search" autocomplete="off">
<label class="md-overlay" data-md-component="overlay" for="__drawer"></label>
<a href="#to-stdout" tabindex="1" class="md-skip">
Skip to content
</a>
<header class="md-header" data-md-component="header">
<nav class="md-header-nav md-grid">
<div class="md-flex">
<div class="md-flex__cell md-flex__cell--shrink">
<a href=".." title="Yq" class="md-header-nav__button md-logo">
<i class="md-icon"></i>
</a>
</div>
<div class="md-flex__cell md-flex__cell--shrink">
<label class="md-icon md-icon--menu md-header-nav__button" for="__drawer"></label>
</div>
<div class="md-flex__cell md-flex__cell--stretch">
<div class="md-flex__ellipsis md-header-nav__title" data-md-component="title">
<span class="md-header-nav__topic">
Yq
</span>
<span class="md-header-nav__topic">
Prefix
</span>
</div>
</div>
<div class="md-flex__cell md-flex__cell--shrink">
<label class="md-icon md-icon--search md-header-nav__button" for="__search"></label>
<div class="md-search" data-md-component="search" role="dialog">
<label class="md-search__overlay" for="__search"></label>
<div class="md-search__inner" role="search">
<form class="md-search__form" name="search">
<input type="text" class="md-search__input" name="query" placeholder="Search" autocapitalize="off" autocorrect="off" autocomplete="off" spellcheck="false" data-md-component="query" data-md-state="active">
<label class="md-icon md-search__icon" for="__search"></label>
<button type="reset" class="md-icon md-search__icon" data-md-component="reset" tabindex="-1">
&#xE5CD;
</button>
</form>
<div class="md-search__output">
<div class="md-search__scrollwrap" data-md-scrollfix>
<div class="md-search-result" data-md-component="result">
<div class="md-search-result__meta">
Type to start searching
</div>
<ol class="md-search-result__list"></ol>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="md-flex__cell md-flex__cell--shrink">
<div class="md-header-nav__source">
<a href="https://github.com/mikefarah/yq/" title="Go to repository" class="md-source" data-md-source="github">
<div class="md-source__icon">
<svg viewBox="0 0 24 24" width="24" height="24">
<use xlink:href="#__github" width="24" height="24"></use>
</svg>
</div>
<div class="md-source__repository">
mikefarah/yq
</div>
</a>
</div>
</div>
</div>
</nav>
</header>
<div class="md-container">
<main class="md-main">
<div class="md-main__inner md-grid" data-md-component="container">
<div class="md-sidebar md-sidebar--primary" data-md-component="navigation">
<div class="md-sidebar__scrollwrap">
<div class="md-sidebar__inner">
<nav class="md-nav md-nav--primary" data-md-level="0">
<label class="md-nav__title md-nav__title--site" for="__drawer">
<a href=".." title="Yq" class="md-nav__button md-logo">
<i class="md-icon"></i>
</a>
Yq
</label>
<div class="md-nav__source">
<a href="https://github.com/mikefarah/yq/" title="Go to repository" class="md-source" data-md-source="github">
<div class="md-source__icon">
<svg viewBox="0 0 24 24" width="24" height="24">
<use xlink:href="#__github" width="24" height="24"></use>
</svg>
</div>
<div class="md-source__repository">
mikefarah/yq
</div>
</a>
</div>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href=".." title="Install" class="md-nav__link">
Install
</a>
</li>
<li class="md-nav__item">
<a href="../read/" title="Read" class="md-nav__link">
Read
</a>
</li>
<li class="md-nav__item">
<a href="../path_expressions/" title="Path Expressions" class="md-nav__link">
Path Expressions
</a>
</li>
<li class="md-nav__item">
<a href="../write/" title="Write/Update" class="md-nav__link">
Write/Update
</a>
</li>
<li class="md-nav__item md-nav__item--active">
<input class="md-toggle md-nav__toggle" data-md-toggle="toc" type="checkbox" id="__toc">
<label class="md-nav__link md-nav__link--active" for="__toc">
Prefix
</label>
<a href="./" title="Prefix" class="md-nav__link md-nav__link--active">
Prefix
</a>
<nav class="md-nav md-nav--secondary">
<label class="md-nav__title" for="__toc">Table of contents</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="#to-stdout" title="To Stdout" class="md-nav__link">
To Stdout
</a>
</li>
<li class="md-nav__item">
<a href="#arbitrary-depth" title="Arbitrary depth" class="md-nav__link">
Arbitrary depth
</a>
</li>
<li class="md-nav__item">
<a href="#updating-files-in-place" title="Updating files in-place" class="md-nav__link">
Updating files in-place
</a>
</li>
<li class="md-nav__item">
<a href="#multiple-documents-prefix-a-single-document" title="Multiple Documents - prefix a single document" class="md-nav__link">
Multiple Documents - prefix a single document
</a>
</li>
<li class="md-nav__item">
<a href="#multiple-documents-prefix-all-documents" title="Multiple Documents - prefix all documents" class="md-nav__link">
Multiple Documents - prefix all documents
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="../delete/" title="Delete" class="md-nav__link">
Delete
</a>
</li>
<li class="md-nav__item">
<a href="../create/" title="Create" class="md-nav__link">
Create
</a>
</li>
<li class="md-nav__item">
<a href="../convert/" title="Convert" class="md-nav__link">
Convert
</a>
</li>
<li class="md-nav__item">
<a href="../merge/" title="Merge" class="md-nav__link">
Merge
</a>
</li>
</ul>
</nav>
</div>
</div>
</div>
<div class="md-sidebar md-sidebar--secondary" data-md-component="toc">
<div class="md-sidebar__scrollwrap">
<div class="md-sidebar__inner">
<nav class="md-nav md-nav--secondary">
<label class="md-nav__title" for="__toc">Table of contents</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="#to-stdout" title="To Stdout" class="md-nav__link">
To Stdout
</a>
</li>
<li class="md-nav__item">
<a href="#arbitrary-depth" title="Arbitrary depth" class="md-nav__link">
Arbitrary depth
</a>
</li>
<li class="md-nav__item">
<a href="#updating-files-in-place" title="Updating files in-place" class="md-nav__link">
Updating files in-place
</a>
</li>
<li class="md-nav__item">
<a href="#multiple-documents-prefix-a-single-document" title="Multiple Documents - prefix a single document" class="md-nav__link">
Multiple Documents - prefix a single document
</a>
</li>
<li class="md-nav__item">
<a href="#multiple-documents-prefix-all-documents" title="Multiple Documents - prefix all documents" class="md-nav__link">
Multiple Documents - prefix all documents
</a>
</li>
</ul>
</nav>
</div>
</div>
</div>
<div class="md-content">
<article class="md-content__inner md-typeset">
<a href="https://github.com/mikefarah/yq/edit/master/docs/prefix.md" title="Edit this page" class="md-icon md-content__icon">&#xE3C9;</a>
<h1>Prefix</h1>
<pre><code>yq p &lt;yaml_file&gt; &lt;path&gt;
</code></pre>
<p>Prefixes a yaml document with the given path expression. The complete yaml content will be nested inside the new prefix path.</p>
<p>See docs for <a href="../path_expressions/">path expression</a> for more details.</p>
<h3 id="to-stdout">To Stdout<a class="headerlink" href="#to-stdout" title="Permanent link">&para;</a></h3>
<p>Given a data1.yaml file of:</p>
<pre><code class="yaml">a: simple
b: [1, 2]
</code></pre>
<p>then</p>
<pre><code class="bash">yq p data1.yaml c
</code></pre>
<p>will output:</p>
<pre><code class="yaml">c:
a: simple
b: [1, 2]
</code></pre>
<h3 id="arbitrary-depth">Arbitrary depth<a class="headerlink" href="#arbitrary-depth" title="Permanent link">&para;</a></h3>
<p>Given a data1.yaml file of:</p>
<pre><code class="yaml">a:
b: [1, 2]
</code></pre>
<p>then</p>
<pre><code class="bash">yq p data1.yaml c.d
</code></pre>
<p>will output:</p>
<pre><code class="yaml">c:
d:
a:
b: [1, 2]
</code></pre>
<h3 id="updating-files-in-place">Updating files in-place<a class="headerlink" href="#updating-files-in-place" title="Permanent link">&para;</a></h3>
<p>Given a data1.yaml file of:</p>
<pre><code class="yaml">a: simple
b: [1, 2]
</code></pre>
<p>then</p>
<pre><code class="bash">yq p -i data1.yaml c
</code></pre>
<p>will update the data1.yaml file so that the path 'c' is prefixed to all other paths.</p>
<h3 id="multiple-documents-prefix-a-single-document">Multiple Documents - prefix a single document<a class="headerlink" href="#multiple-documents-prefix-a-single-document" title="Permanent link">&para;</a></h3>
<p>Given a data1.yaml file of:</p>
<pre><code class="yaml">something: else
---
a: simple
b: cat
</code></pre>
<p>then</p>
<pre><code class="bash">yq p -d1 data1.yaml c
</code></pre>
<p>will output:</p>
<pre><code class="yaml">something: else
---
c:
a: simple
b: cat
</code></pre>
<h3 id="multiple-documents-prefix-all-documents">Multiple Documents - prefix all documents<a class="headerlink" href="#multiple-documents-prefix-all-documents" title="Permanent link">&para;</a></h3>
<p>Given a data1.yaml file of:</p>
<pre><code class="yaml">something: else
---
a: simple
b: cat
</code></pre>
<p>then</p>
<pre><code class="bash">yq p -d'*' data1.yaml c
</code></pre>
<p>will output:</p>
<pre><code class="yaml">c:
something: else
---
c:
a: simple
b: cat
</code></pre>
</article>
</div>
</div>
</main>
<footer class="md-footer">
<div class="md-footer-nav">
<nav class="md-footer-nav__inner md-grid">
<a href="../write/" title="Write/Update" class="md-flex md-footer-nav__link md-footer-nav__link--prev" rel="prev">
<div class="md-flex__cell md-flex__cell--shrink">
<i class="md-icon md-icon--arrow-back md-footer-nav__button"></i>
</div>
<div class="md-flex__cell md-flex__cell--stretch md-footer-nav__title">
<span class="md-flex__ellipsis">
<span class="md-footer-nav__direction">
Previous
</span>
Write/Update
</span>
</div>
</a>
<a href="../delete/" title="Delete" class="md-flex md-footer-nav__link md-footer-nav__link--next" rel="next">
<div class="md-flex__cell md-flex__cell--stretch md-footer-nav__title">
<span class="md-flex__ellipsis">
<span class="md-footer-nav__direction">
Next
</span>
Delete
</span>
</div>
<div class="md-flex__cell md-flex__cell--shrink">
<i class="md-icon md-icon--arrow-forward md-footer-nav__button"></i>
</div>
</a>
</nav>
</div>
<div class="md-footer-meta md-typeset">
<div class="md-footer-meta__inner md-grid">
<div class="md-footer-copyright">
powered by
<a href="https://www.mkdocs.org">MkDocs</a>
and
<a href="https://squidfunk.github.io/mkdocs-material/">
Material for MkDocs</a>
</div>
<div class="md-footer-social">
<link rel="stylesheet" href="../assets/fonts/font-awesome.css">
<a href="https://github.com/mikefarah" class="md-footer-social__link fa fa-github"></a>
<a href="https://www.linkedin.com/in/mike-farah-b5a75b2/" class="md-footer-social__link fa fa-linkedin"></a>
</div>
</div>
</div>
</footer>
</div>
<script src="../assets/javascripts/application.39abc4af.js"></script>
<script>app.initialize({version:"1.0.4",url:{base:".."}})</script>
</body>
</html>

View File

@@ -1,734 +0,0 @@
<!doctype html>
<html lang="en" class="no-js">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta http-equiv="x-ua-compatible" content="ie=edge">
<meta name="lang:clipboard.copy" content="Copy to clipboard">
<meta name="lang:clipboard.copied" content="Copied to clipboard">
<meta name="lang:search.language" content="en">
<meta name="lang:search.pipeline.stopwords" content="True">
<meta name="lang:search.pipeline.trimmer" content="True">
<meta name="lang:search.result.none" content="No matching documents">
<meta name="lang:search.result.one" content="1 matching document">
<meta name="lang:search.result.other" content="# matching documents">
<meta name="lang:search.tokenizer" content="[\s\-]+">
<link rel="shortcut icon" href="../assets/images/favicon.png">
<meta name="generator" content="mkdocs-1.0.4, mkdocs-material-4.2.0">
<title>Read - Yq</title>
<link rel="stylesheet" href="../assets/stylesheets/application.750b69bd.css">
<script src="../assets/javascripts/modernizr.74668098.js"></script>
<link href="https://fonts.gstatic.com" rel="preconnect" crossorigin>
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:300,400,400i,700|Roboto+Mono">
<style>body,input{font-family:"Roboto","Helvetica Neue",Helvetica,Arial,sans-serif}code,kbd,pre{font-family:"Roboto Mono","Courier New",Courier,monospace}</style>
<link rel="stylesheet" href="../assets/fonts/material-icons.css">
</head>
<body dir="ltr">
<svg class="md-svg">
<defs>
<svg xmlns="http://www.w3.org/2000/svg" width="416" height="448"
viewBox="0 0 416 448" id="__github">
<path fill="currentColor" d="M160 304q0 10-3.125 20.5t-10.75 19-18.125
8.5-18.125-8.5-10.75-19-3.125-20.5 3.125-20.5 10.75-19 18.125-8.5
18.125 8.5 10.75 19 3.125 20.5zM320 304q0 10-3.125 20.5t-10.75
19-18.125 8.5-18.125-8.5-10.75-19-3.125-20.5 3.125-20.5 10.75-19
18.125-8.5 18.125 8.5 10.75 19 3.125 20.5zM360
304q0-30-17.25-51t-46.75-21q-10.25 0-48.75 5.25-17.75 2.75-39.25
2.75t-39.25-2.75q-38-5.25-48.75-5.25-29.5 0-46.75 21t-17.25 51q0 22 8
38.375t20.25 25.75 30.5 15 35 7.375 37.25 1.75h42q20.5 0
37.25-1.75t35-7.375 30.5-15 20.25-25.75 8-38.375zM416 260q0 51.75-15.25
82.75-9.5 19.25-26.375 33.25t-35.25 21.5-42.5 11.875-42.875 5.5-41.75
1.125q-19.5 0-35.5-0.75t-36.875-3.125-38.125-7.5-34.25-12.875-30.25-20.25-21.5-28.75q-15.5-30.75-15.5-82.75
0-59.25 34-99-6.75-20.5-6.75-42.5 0-29 12.75-54.5 27 0 47.5 9.875t47.25
30.875q36.75-8.75 77.25-8.75 37 0 70 8 26.25-20.5
46.75-30.25t47.25-9.75q12.75 25.5 12.75 54.5 0 21.75-6.75 42 34 40 34
99.5z" />
</svg>
</defs>
</svg>
<input class="md-toggle" data-md-toggle="drawer" type="checkbox" id="__drawer" autocomplete="off">
<input class="md-toggle" data-md-toggle="search" type="checkbox" id="__search" autocomplete="off">
<label class="md-overlay" data-md-component="overlay" for="__drawer"></label>
<a href="#basic" tabindex="1" class="md-skip">
Skip to content
</a>
<header class="md-header" data-md-component="header">
<nav class="md-header-nav md-grid">
<div class="md-flex">
<div class="md-flex__cell md-flex__cell--shrink">
<a href=".." title="Yq" class="md-header-nav__button md-logo">
<i class="md-icon"></i>
</a>
</div>
<div class="md-flex__cell md-flex__cell--shrink">
<label class="md-icon md-icon--menu md-header-nav__button" for="__drawer"></label>
</div>
<div class="md-flex__cell md-flex__cell--stretch">
<div class="md-flex__ellipsis md-header-nav__title" data-md-component="title">
<span class="md-header-nav__topic">
Yq
</span>
<span class="md-header-nav__topic">
Read
</span>
</div>
</div>
<div class="md-flex__cell md-flex__cell--shrink">
<label class="md-icon md-icon--search md-header-nav__button" for="__search"></label>
<div class="md-search" data-md-component="search" role="dialog">
<label class="md-search__overlay" for="__search"></label>
<div class="md-search__inner" role="search">
<form class="md-search__form" name="search">
<input type="text" class="md-search__input" name="query" placeholder="Search" autocapitalize="off" autocorrect="off" autocomplete="off" spellcheck="false" data-md-component="query" data-md-state="active">
<label class="md-icon md-search__icon" for="__search"></label>
<button type="reset" class="md-icon md-search__icon" data-md-component="reset" tabindex="-1">
&#xE5CD;
</button>
</form>
<div class="md-search__output">
<div class="md-search__scrollwrap" data-md-scrollfix>
<div class="md-search-result" data-md-component="result">
<div class="md-search-result__meta">
Type to start searching
</div>
<ol class="md-search-result__list"></ol>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="md-flex__cell md-flex__cell--shrink">
<div class="md-header-nav__source">
<a href="https://github.com/mikefarah/yq/" title="Go to repository" class="md-source" data-md-source="github">
<div class="md-source__icon">
<svg viewBox="0 0 24 24" width="24" height="24">
<use xlink:href="#__github" width="24" height="24"></use>
</svg>
</div>
<div class="md-source__repository">
mikefarah/yq
</div>
</a>
</div>
</div>
</div>
</nav>
</header>
<div class="md-container">
<main class="md-main">
<div class="md-main__inner md-grid" data-md-component="container">
<div class="md-sidebar md-sidebar--primary" data-md-component="navigation">
<div class="md-sidebar__scrollwrap">
<div class="md-sidebar__inner">
<nav class="md-nav md-nav--primary" data-md-level="0">
<label class="md-nav__title md-nav__title--site" for="__drawer">
<a href=".." title="Yq" class="md-nav__button md-logo">
<i class="md-icon"></i>
</a>
Yq
</label>
<div class="md-nav__source">
<a href="https://github.com/mikefarah/yq/" title="Go to repository" class="md-source" data-md-source="github">
<div class="md-source__icon">
<svg viewBox="0 0 24 24" width="24" height="24">
<use xlink:href="#__github" width="24" height="24"></use>
</svg>
</div>
<div class="md-source__repository">
mikefarah/yq
</div>
</a>
</div>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href=".." title="Install" class="md-nav__link">
Install
</a>
</li>
<li class="md-nav__item md-nav__item--active">
<input class="md-toggle md-nav__toggle" data-md-toggle="toc" type="checkbox" id="__toc">
<label class="md-nav__link md-nav__link--active" for="__toc">
Read
</label>
<a href="./" title="Read" class="md-nav__link md-nav__link--active">
Read
</a>
<nav class="md-nav md-nav--secondary">
<label class="md-nav__title" for="__toc">Table of contents</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="#basic" title="Basic" class="md-nav__link">
Basic
</a>
</li>
<li class="md-nav__item">
<a href="#from-stdin" title="From Stdin" class="md-nav__link">
From Stdin
</a>
</li>
<li class="md-nav__item">
<a href="#splat" title="Splat" class="md-nav__link">
Splat
</a>
</li>
<li class="md-nav__item">
<a href="#prefix-splat" title="Prefix Splat" class="md-nav__link">
Prefix Splat
</a>
</li>
<li class="md-nav__item">
<a href="#multiple-documents-specify-a-single-document" title="Multiple Documents - specify a single document" class="md-nav__link">
Multiple Documents - specify a single document
</a>
</li>
<li class="md-nav__item">
<a href="#multiple-documents-read-all-documents" title="Multiple Documents - read all documents" class="md-nav__link">
Multiple Documents - read all documents
</a>
</li>
<li class="md-nav__item">
<a href="#arrays" title="Arrays" class="md-nav__link">
Arrays
</a>
</li>
<li class="md-nav__item">
<a href="#array-splat" title="Array Splat" class="md-nav__link">
Array Splat
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="../path_expressions/" title="Path Expressions" class="md-nav__link">
Path Expressions
</a>
</li>
<li class="md-nav__item">
<a href="../write/" title="Write/Update" class="md-nav__link">
Write/Update
</a>
</li>
<li class="md-nav__item">
<a href="../prefix/" title="Prefix" class="md-nav__link">
Prefix
</a>
</li>
<li class="md-nav__item">
<a href="../delete/" title="Delete" class="md-nav__link">
Delete
</a>
</li>
<li class="md-nav__item">
<a href="../create/" title="Create" class="md-nav__link">
Create
</a>
</li>
<li class="md-nav__item">
<a href="../convert/" title="Convert" class="md-nav__link">
Convert
</a>
</li>
<li class="md-nav__item">
<a href="../merge/" title="Merge" class="md-nav__link">
Merge
</a>
</li>
</ul>
</nav>
</div>
</div>
</div>
<div class="md-sidebar md-sidebar--secondary" data-md-component="toc">
<div class="md-sidebar__scrollwrap">
<div class="md-sidebar__inner">
<nav class="md-nav md-nav--secondary">
<label class="md-nav__title" for="__toc">Table of contents</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="#basic" title="Basic" class="md-nav__link">
Basic
</a>
</li>
<li class="md-nav__item">
<a href="#from-stdin" title="From Stdin" class="md-nav__link">
From Stdin
</a>
</li>
<li class="md-nav__item">
<a href="#splat" title="Splat" class="md-nav__link">
Splat
</a>
</li>
<li class="md-nav__item">
<a href="#prefix-splat" title="Prefix Splat" class="md-nav__link">
Prefix Splat
</a>
</li>
<li class="md-nav__item">
<a href="#multiple-documents-specify-a-single-document" title="Multiple Documents - specify a single document" class="md-nav__link">
Multiple Documents - specify a single document
</a>
</li>
<li class="md-nav__item">
<a href="#multiple-documents-read-all-documents" title="Multiple Documents - read all documents" class="md-nav__link">
Multiple Documents - read all documents
</a>
</li>
<li class="md-nav__item">
<a href="#arrays" title="Arrays" class="md-nav__link">
Arrays
</a>
</li>
<li class="md-nav__item">
<a href="#array-splat" title="Array Splat" class="md-nav__link">
Array Splat
</a>
</li>
</ul>
</nav>
</div>
</div>
</div>
<div class="md-content">
<article class="md-content__inner md-typeset">
<a href="https://github.com/mikefarah/yq/edit/master/docs/read.md" title="Edit this page" class="md-icon md-content__icon">&#xE3C9;</a>
<h1>Read</h1>
<pre><code>yq r &lt;yaml_file|json_file&gt; &lt;path_expression&gt;
</code></pre>
<p>Returns the matching nodes of the path expression for the given yaml file (or STDIN).</p>
<p>See docs for <a href="../path_expressions/">path expression</a> for more details.</p>
<h3 id="basic">Basic<a class="headerlink" href="#basic" title="Permanent link">&para;</a></h3>
<p>Given a sample.yaml file of:</p>
<pre><code class="yaml">b:
c: 2
</code></pre>
<p>then</p>
<pre><code class="bash">yq r sample.yaml b.c
</code></pre>
<p>will output the value of '2'.</p>
<h3 id="from-stdin">From Stdin<a class="headerlink" href="#from-stdin" title="Permanent link">&para;</a></h3>
<p>Given a sample.yaml file of:</p>
<pre><code class="bash">cat sample.yaml | yq r - b.c
</code></pre>
<p>will output the value of '2'.</p>
<h3 id="splat">Splat<a class="headerlink" href="#splat" title="Permanent link">&para;</a></h3>
<p>Given a sample.yaml file of:</p>
<pre><code class="yaml">---
bob:
item1:
cats: bananas
item2:
cats: apples
thing:
cats: oranges
</code></pre>
<p>then</p>
<pre><code class="bash">yq r sample.yaml bob.*.cats
</code></pre>
<p>will output</p>
<pre><code class="yaml">- bananas
- apples
- oranges
</code></pre>
<h3 id="prefix-splat">Prefix Splat<a class="headerlink" href="#prefix-splat" title="Permanent link">&para;</a></h3>
<p>Given a sample.yaml file of:</p>
<pre><code class="yaml">---
bob:
item1:
cats: bananas
item2:
cats: apples
thing:
cats: oranges
</code></pre>
<p>then</p>
<pre><code class="bash">yq r sample.yaml bob.item*.cats
</code></pre>
<p>will output</p>
<pre><code class="yaml">- bananas
- apples
</code></pre>
<h3 id="multiple-documents-specify-a-single-document">Multiple Documents - specify a single document<a class="headerlink" href="#multiple-documents-specify-a-single-document" title="Permanent link">&para;</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="multiple-documents-read-all-documents">Multiple Documents - read all documents<a class="headerlink" href="#multiple-documents-read-all-documents" title="Permanent link">&para;</a></h3>
<p>Reading all documents will return the result as an array. This can be converted to json using the '-j' flag if desired.</p>
<p>Given a sample.yaml file of:</p>
<pre><code class="yaml">name: Fred
age: 22
---
name: Stella
age: 23
---
name: Android
age: 232
</code></pre>
<p>then</p>
<pre><code class="bash">yq r -d'*' sample.yaml name
</code></pre>
<p>will output:</p>
<pre><code>- Fred
- Stella
- Android
</code></pre>
<h3 id="arrays">Arrays<a class="headerlink" href="#arrays" title="Permanent link">&para;</a></h3>
<p>You can give an index to access a specific element:
e.g.: given a sample file of</p>
<pre><code class="yaml">b:
e:
- name: fred
value: 3
- name: sam
value: 4
</code></pre>
<p>then</p>
<pre><code>yq r sample.yaml 'b.e[1].name'
</code></pre>
<p>will output 'sam'</p>
<p>Note that the path is in quotes to avoid the square brackets being interpreted by your shell.</p>
<h3 id="array-splat">Array Splat<a class="headerlink" href="#array-splat" title="Permanent link">&para;</a></h3>
<p>e.g.: given a sample file of</p>
<pre><code class="yaml">b:
e:
- name: fred
value: 3
- name: sam
value: 4
</code></pre>
<p>then</p>
<pre><code>yq r sample.yaml 'b.e[*].name'
</code></pre>
<p>will output:</p>
<pre><code>- fred
- sam
</code></pre>
<p>Note that the path is in quotes to avoid the square brackets being interpreted by your shell.</p>
</article>
</div>
</div>
</main>
<footer class="md-footer">
<div class="md-footer-nav">
<nav class="md-footer-nav__inner md-grid">
<a href=".." title="Install" class="md-flex md-footer-nav__link md-footer-nav__link--prev" rel="prev">
<div class="md-flex__cell md-flex__cell--shrink">
<i class="md-icon md-icon--arrow-back md-footer-nav__button"></i>
</div>
<div class="md-flex__cell md-flex__cell--stretch md-footer-nav__title">
<span class="md-flex__ellipsis">
<span class="md-footer-nav__direction">
Previous
</span>
Install
</span>
</div>
</a>
<a href="../path_expressions/" title="Path Expressions" class="md-flex md-footer-nav__link md-footer-nav__link--next" rel="next">
<div class="md-flex__cell md-flex__cell--stretch md-footer-nav__title">
<span class="md-flex__ellipsis">
<span class="md-footer-nav__direction">
Next
</span>
Path Expressions
</span>
</div>
<div class="md-flex__cell md-flex__cell--shrink">
<i class="md-icon md-icon--arrow-forward md-footer-nav__button"></i>
</div>
</a>
</nav>
</div>
<div class="md-footer-meta md-typeset">
<div class="md-footer-meta__inner md-grid">
<div class="md-footer-copyright">
powered by
<a href="https://www.mkdocs.org">MkDocs</a>
and
<a href="https://squidfunk.github.io/mkdocs-material/">
Material for MkDocs</a>
</div>
<div class="md-footer-social">
<link rel="stylesheet" href="../assets/fonts/font-awesome.css">
<a href="https://github.com/mikefarah" class="md-footer-social__link fa fa-github"></a>
<a href="https://www.linkedin.com/in/mike-farah-b5a75b2/" class="md-footer-social__link fa fa-linkedin"></a>
</div>
</div>
</div>
</footer>
</div>
<script src="../assets/javascripts/application.39abc4af.js"></script>
<script>app.initialize({version:"1.0.4",url:{base:".."}})</script>
</body>
</html>

File diff suppressed because one or more lines are too long

View File

@@ -2,47 +2,7 @@
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
<url>
<loc>None</loc>
<lastmod>2020-01-13</lastmod>
<changefreq>daily</changefreq>
</url>
<url>
<loc>None</loc>
<lastmod>2020-01-13</lastmod>
<changefreq>daily</changefreq>
</url>
<url>
<loc>None</loc>
<lastmod>2020-01-13</lastmod>
<changefreq>daily</changefreq>
</url>
<url>
<loc>None</loc>
<lastmod>2020-01-13</lastmod>
<changefreq>daily</changefreq>
</url>
<url>
<loc>None</loc>
<lastmod>2020-01-13</lastmod>
<changefreq>daily</changefreq>
</url>
<url>
<loc>None</loc>
<lastmod>2020-01-13</lastmod>
<changefreq>daily</changefreq>
</url>
<url>
<loc>None</loc>
<lastmod>2020-01-13</lastmod>
<changefreq>daily</changefreq>
</url>
<url>
<loc>None</loc>
<lastmod>2020-01-13</lastmod>
<changefreq>daily</changefreq>
</url>
<url>
<loc>None</loc>
<lastmod>2020-01-13</lastmod>
<lastmod>2020-01-30</lastmod>
<changefreq>daily</changefreq>
</url>
</urlset>

Binary file not shown.

View File

@@ -1,881 +0,0 @@
<!doctype html>
<html lang="en" class="no-js">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta http-equiv="x-ua-compatible" content="ie=edge">
<meta name="lang:clipboard.copy" content="Copy to clipboard">
<meta name="lang:clipboard.copied" content="Copied to clipboard">
<meta name="lang:search.language" content="en">
<meta name="lang:search.pipeline.stopwords" content="True">
<meta name="lang:search.pipeline.trimmer" content="True">
<meta name="lang:search.result.none" content="No matching documents">
<meta name="lang:search.result.one" content="1 matching document">
<meta name="lang:search.result.other" content="# matching documents">
<meta name="lang:search.tokenizer" content="[\s\-]+">
<link rel="shortcut icon" href="../assets/images/favicon.png">
<meta name="generator" content="mkdocs-1.0.4, mkdocs-material-4.2.0">
<title>Write/Update - Yq</title>
<link rel="stylesheet" href="../assets/stylesheets/application.750b69bd.css">
<script src="../assets/javascripts/modernizr.74668098.js"></script>
<link href="https://fonts.gstatic.com" rel="preconnect" crossorigin>
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:300,400,400i,700|Roboto+Mono">
<style>body,input{font-family:"Roboto","Helvetica Neue",Helvetica,Arial,sans-serif}code,kbd,pre{font-family:"Roboto Mono","Courier New",Courier,monospace}</style>
<link rel="stylesheet" href="../assets/fonts/material-icons.css">
</head>
<body dir="ltr">
<svg class="md-svg">
<defs>
<svg xmlns="http://www.w3.org/2000/svg" width="416" height="448"
viewBox="0 0 416 448" id="__github">
<path fill="currentColor" d="M160 304q0 10-3.125 20.5t-10.75 19-18.125
8.5-18.125-8.5-10.75-19-3.125-20.5 3.125-20.5 10.75-19 18.125-8.5
18.125 8.5 10.75 19 3.125 20.5zM320 304q0 10-3.125 20.5t-10.75
19-18.125 8.5-18.125-8.5-10.75-19-3.125-20.5 3.125-20.5 10.75-19
18.125-8.5 18.125 8.5 10.75 19 3.125 20.5zM360
304q0-30-17.25-51t-46.75-21q-10.25 0-48.75 5.25-17.75 2.75-39.25
2.75t-39.25-2.75q-38-5.25-48.75-5.25-29.5 0-46.75 21t-17.25 51q0 22 8
38.375t20.25 25.75 30.5 15 35 7.375 37.25 1.75h42q20.5 0
37.25-1.75t35-7.375 30.5-15 20.25-25.75 8-38.375zM416 260q0 51.75-15.25
82.75-9.5 19.25-26.375 33.25t-35.25 21.5-42.5 11.875-42.875 5.5-41.75
1.125q-19.5 0-35.5-0.75t-36.875-3.125-38.125-7.5-34.25-12.875-30.25-20.25-21.5-28.75q-15.5-30.75-15.5-82.75
0-59.25 34-99-6.75-20.5-6.75-42.5 0-29 12.75-54.5 27 0 47.5 9.875t47.25
30.875q36.75-8.75 77.25-8.75 37 0 70 8 26.25-20.5
46.75-30.25t47.25-9.75q12.75 25.5 12.75 54.5 0 21.75-6.75 42 34 40 34
99.5z" />
</svg>
</defs>
</svg>
<input class="md-toggle" data-md-toggle="drawer" type="checkbox" id="__drawer" autocomplete="off">
<input class="md-toggle" data-md-toggle="search" type="checkbox" id="__search" autocomplete="off">
<label class="md-overlay" data-md-component="overlay" for="__drawer"></label>
<a href="#to-stdout" tabindex="1" class="md-skip">
Skip to content
</a>
<header class="md-header" data-md-component="header">
<nav class="md-header-nav md-grid">
<div class="md-flex">
<div class="md-flex__cell md-flex__cell--shrink">
<a href=".." title="Yq" class="md-header-nav__button md-logo">
<i class="md-icon"></i>
</a>
</div>
<div class="md-flex__cell md-flex__cell--shrink">
<label class="md-icon md-icon--menu md-header-nav__button" for="__drawer"></label>
</div>
<div class="md-flex__cell md-flex__cell--stretch">
<div class="md-flex__ellipsis md-header-nav__title" data-md-component="title">
<span class="md-header-nav__topic">
Yq
</span>
<span class="md-header-nav__topic">
Write/Update
</span>
</div>
</div>
<div class="md-flex__cell md-flex__cell--shrink">
<label class="md-icon md-icon--search md-header-nav__button" for="__search"></label>
<div class="md-search" data-md-component="search" role="dialog">
<label class="md-search__overlay" for="__search"></label>
<div class="md-search__inner" role="search">
<form class="md-search__form" name="search">
<input type="text" class="md-search__input" name="query" placeholder="Search" autocapitalize="off" autocorrect="off" autocomplete="off" spellcheck="false" data-md-component="query" data-md-state="active">
<label class="md-icon md-search__icon" for="__search"></label>
<button type="reset" class="md-icon md-search__icon" data-md-component="reset" tabindex="-1">
&#xE5CD;
</button>
</form>
<div class="md-search__output">
<div class="md-search__scrollwrap" data-md-scrollfix>
<div class="md-search-result" data-md-component="result">
<div class="md-search-result__meta">
Type to start searching
</div>
<ol class="md-search-result__list"></ol>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="md-flex__cell md-flex__cell--shrink">
<div class="md-header-nav__source">
<a href="https://github.com/mikefarah/yq/" title="Go to repository" class="md-source" data-md-source="github">
<div class="md-source__icon">
<svg viewBox="0 0 24 24" width="24" height="24">
<use xlink:href="#__github" width="24" height="24"></use>
</svg>
</div>
<div class="md-source__repository">
mikefarah/yq
</div>
</a>
</div>
</div>
</div>
</nav>
</header>
<div class="md-container">
<main class="md-main">
<div class="md-main__inner md-grid" data-md-component="container">
<div class="md-sidebar md-sidebar--primary" data-md-component="navigation">
<div class="md-sidebar__scrollwrap">
<div class="md-sidebar__inner">
<nav class="md-nav md-nav--primary" data-md-level="0">
<label class="md-nav__title md-nav__title--site" for="__drawer">
<a href=".." title="Yq" class="md-nav__button md-logo">
<i class="md-icon"></i>
</a>
Yq
</label>
<div class="md-nav__source">
<a href="https://github.com/mikefarah/yq/" title="Go to repository" class="md-source" data-md-source="github">
<div class="md-source__icon">
<svg viewBox="0 0 24 24" width="24" height="24">
<use xlink:href="#__github" width="24" height="24"></use>
</svg>
</div>
<div class="md-source__repository">
mikefarah/yq
</div>
</a>
</div>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href=".." title="Install" class="md-nav__link">
Install
</a>
</li>
<li class="md-nav__item">
<a href="../read/" title="Read" class="md-nav__link">
Read
</a>
</li>
<li class="md-nav__item">
<a href="../path_expressions/" title="Path Expressions" class="md-nav__link">
Path Expressions
</a>
</li>
<li class="md-nav__item md-nav__item--active">
<input class="md-toggle md-nav__toggle" data-md-toggle="toc" type="checkbox" id="__toc">
<label class="md-nav__link md-nav__link--active" for="__toc">
Write/Update
</label>
<a href="./" title="Write/Update" class="md-nav__link md-nav__link--active">
Write/Update
</a>
<nav class="md-nav md-nav--secondary">
<label class="md-nav__title" for="__toc">Table of contents</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="#to-stdout" title="To Stdout" class="md-nav__link">
To Stdout
</a>
</li>
<li class="md-nav__item">
<a href="#from-stdin" title="From STDIN" class="md-nav__link">
From STDIN
</a>
</li>
<li class="md-nav__item">
<a href="#adding-new-fields" title="Adding new fields" class="md-nav__link">
Adding new fields
</a>
</li>
<li class="md-nav__item">
<a href="#splat" title="Splat" class="md-nav__link">
Splat
</a>
</li>
<li class="md-nav__item">
<a href="#prefix-splat" title="Prefix Splat" class="md-nav__link">
Prefix Splat
</a>
</li>
<li class="md-nav__item">
<a href="#array-splat" title="Array Splat" class="md-nav__link">
Array Splat
</a>
</li>
<li class="md-nav__item">
<a href="#appending-value-to-an-array-field" title="Appending value to an array field" class="md-nav__link">
Appending value to an array field
</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 class="md-nav__item">
<a href="#updating-files-in-place" title="Updating files in-place" class="md-nav__link">
Updating files in-place
</a>
</li>
<li class="md-nav__item">
<a href="#updating-multiple-values-with-a-script" title="Updating multiple values with a script" class="md-nav__link">
Updating multiple values with a script
</a>
</li>
<li class="md-nav__item">
<a href="#values-starting-with-a-hyphen-or-dash" title="Values starting with a hyphen (or dash)" class="md-nav__link">
Values starting with a hyphen (or dash)
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="../prefix/" title="Prefix" class="md-nav__link">
Prefix
</a>
</li>
<li class="md-nav__item">
<a href="../delete/" title="Delete" class="md-nav__link">
Delete
</a>
</li>
<li class="md-nav__item">
<a href="../create/" title="Create" class="md-nav__link">
Create
</a>
</li>
<li class="md-nav__item">
<a href="../convert/" title="Convert" class="md-nav__link">
Convert
</a>
</li>
<li class="md-nav__item">
<a href="../merge/" title="Merge" class="md-nav__link">
Merge
</a>
</li>
</ul>
</nav>
</div>
</div>
</div>
<div class="md-sidebar md-sidebar--secondary" data-md-component="toc">
<div class="md-sidebar__scrollwrap">
<div class="md-sidebar__inner">
<nav class="md-nav md-nav--secondary">
<label class="md-nav__title" for="__toc">Table of contents</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="#to-stdout" title="To Stdout" class="md-nav__link">
To Stdout
</a>
</li>
<li class="md-nav__item">
<a href="#from-stdin" title="From STDIN" class="md-nav__link">
From STDIN
</a>
</li>
<li class="md-nav__item">
<a href="#adding-new-fields" title="Adding new fields" class="md-nav__link">
Adding new fields
</a>
</li>
<li class="md-nav__item">
<a href="#splat" title="Splat" class="md-nav__link">
Splat
</a>
</li>
<li class="md-nav__item">
<a href="#prefix-splat" title="Prefix Splat" class="md-nav__link">
Prefix Splat
</a>
</li>
<li class="md-nav__item">
<a href="#array-splat" title="Array Splat" class="md-nav__link">
Array Splat
</a>
</li>
<li class="md-nav__item">
<a href="#appending-value-to-an-array-field" title="Appending value to an array field" class="md-nav__link">
Appending value to an array field
</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 class="md-nav__item">
<a href="#updating-files-in-place" title="Updating files in-place" class="md-nav__link">
Updating files in-place
</a>
</li>
<li class="md-nav__item">
<a href="#updating-multiple-values-with-a-script" title="Updating multiple values with a script" class="md-nav__link">
Updating multiple values with a script
</a>
</li>
<li class="md-nav__item">
<a href="#values-starting-with-a-hyphen-or-dash" title="Values starting with a hyphen (or dash)" class="md-nav__link">
Values starting with a hyphen (or dash)
</a>
</li>
</ul>
</nav>
</div>
</div>
</div>
<div class="md-content">
<article class="md-content__inner md-typeset">
<a href="https://github.com/mikefarah/yq/edit/master/docs/write.md" title="Edit this page" class="md-icon md-content__icon">&#xE3C9;</a>
<h1>Write/Update</h1>
<pre><code>yq w &lt;yaml_file&gt; &lt;path_expression&gt; &lt;new value&gt;
</code></pre>
<p>Updates all the matching nodes of path expression to the supplied value.</p>
<p>See docs for <a href="../path_expressions/">path expression</a> for more details.</p>
<h3 id="to-stdout">To Stdout<a class="headerlink" href="#to-stdout" title="Permanent link">&para;</a></h3>
<p>Given a sample.yaml file of:</p>
<pre><code class="yaml">b:
c: 2
</code></pre>
<p>then</p>
<pre><code class="bash">yq w sample.yaml b.c cat
</code></pre>
<p>will output:</p>
<pre><code class="yaml">b:
c: cat
</code></pre>
<h3 id="from-stdin">From STDIN<a class="headerlink" href="#from-stdin" title="Permanent link">&para;</a></h3>
<pre><code class="bash">cat sample.yaml | yq w - b.c blah
</code></pre>
<h3 id="adding-new-fields">Adding new fields<a class="headerlink" href="#adding-new-fields" title="Permanent link">&para;</a></h3>
<p>Any missing fields in the path will be created on the fly.</p>
<p>Given a sample.yaml file of:</p>
<pre><code class="yaml">b:
c: 2
</code></pre>
<p>then</p>
<pre><code class="bash">yq w sample.yaml b.d[+] &quot;new thing&quot;
</code></pre>
<p>will output:</p>
<pre><code class="yaml">b:
c: cat
d:
- new thing
</code></pre>
<h3 id="splat">Splat<a class="headerlink" href="#splat" title="Permanent link">&para;</a></h3>
<p>Given a sample.yaml file of:</p>
<pre><code class="yaml">---
bob:
item1:
cats: bananas
item2:
cats: apples
thing:
cats: oranges
</code></pre>
<p>then</p>
<pre><code class="bash">yq w sample.yaml bob.*.cats meow
</code></pre>
<p>will output:</p>
<pre><code class="yaml">---
bob:
item1:
cats: meow
item2:
cats: meow
thing:
cats: meow
</code></pre>
<h3 id="prefix-splat">Prefix Splat<a class="headerlink" href="#prefix-splat" title="Permanent link">&para;</a></h3>
<p>Given a sample.yaml file of:</p>
<pre><code class="yaml">---
bob:
item1:
cats: bananas
item2:
cats: apples
thing:
cats: oranges
</code></pre>
<p>then</p>
<pre><code class="bash">yq w sample.yaml bob.item*.cats meow
</code></pre>
<p>will output:</p>
<pre><code class="yaml">---
bob:
item1:
cats: meow
item2:
cats: meow
thing:
cats: oranges
</code></pre>
<h3 id="array-splat">Array Splat<a class="headerlink" href="#array-splat" title="Permanent link">&para;</a></h3>
<p>Given a sample.yaml file of:</p>
<pre><code class="yaml">---
bob:
- cats: bananas
- cats: apples
- cats: oranges
</code></pre>
<p>then</p>
<pre><code class="bash">yq w sample.yaml bob[*].cats meow
</code></pre>
<p>will output:</p>
<pre><code class="yaml">---
bob:
- cats: meow
- cats: meow
- cats: meow
</code></pre>
<h3 id="appending-value-to-an-array-field">Appending value to an array field<a class="headerlink" href="#appending-value-to-an-array-field" title="Permanent link">&para;</a></h3>
<p>Given a sample.yaml file of:</p>
<pre><code class="yaml">b:
c: 2
d:
- new thing
- foo thing
</code></pre>
<p>then</p>
<pre><code class="bash">yq w sample.yaml &quot;b.d[+]&quot; &quot;bar thing&quot;
</code></pre>
<p>will output:</p>
<pre><code class="yaml">b:
c: cat
d:
- new thing
- foo thing
- bar thing
</code></pre>
<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">&para;</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">&para;</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">&para;</a></h3>
<p>Given a sample.yaml file of:</p>
<pre><code class="yaml">b:
c: 2
</code></pre>
<p>then</p>
<pre><code class="bash">yq w -i sample.yaml b.c cat
</code></pre>
<p>will update the sample.yaml file so that the value of 'c' is cat.</p>
<h3 id="updating-multiple-values-with-a-script">Updating multiple values with a script<a class="headerlink" href="#updating-multiple-values-with-a-script" title="Permanent link">&para;</a></h3>
<p>Given a sample.yaml file of:</p>
<pre><code class="yaml">b:
c: 2
e:
- name: Billy Bob
</code></pre>
<p>and a script update_instructions.yaml of:</p>
<pre><code class="yaml">b.c: 3
b.e[+].name: Howdy Partner
</code></pre>
<p>then</p>
<pre><code class="bash">yq w -s update_instructions.yaml sample.yaml
</code></pre>
<p>will output:</p>
<pre><code class="yaml">b:
c: 3
e:
- name: Howdy Partner
</code></pre>
<p>And, of course, you can pipe the instructions in using '-':</p>
<pre><code class="bash">cat update_instructions.yaml | yq w -s - sample.yaml
</code></pre>
<h3 id="values-starting-with-a-hyphen-or-dash">Values starting with a hyphen (or dash)<a class="headerlink" href="#values-starting-with-a-hyphen-or-dash" title="Permanent link">&para;</a></h3>
<p>The flag terminator needs to be used to stop the app from attempting to parse the subsequent arguments as flags:</p>
<pre><code>yq w -- my.path -3
</code></pre>
<p>will output</p>
<pre><code class="yaml">my:
path: -3
</code></pre>
</article>
</div>
</div>
</main>
<footer class="md-footer">
<div class="md-footer-nav">
<nav class="md-footer-nav__inner md-grid">
<a href="../path_expressions/" title="Path Expressions" class="md-flex md-footer-nav__link md-footer-nav__link--prev" rel="prev">
<div class="md-flex__cell md-flex__cell--shrink">
<i class="md-icon md-icon--arrow-back md-footer-nav__button"></i>
</div>
<div class="md-flex__cell md-flex__cell--stretch md-footer-nav__title">
<span class="md-flex__ellipsis">
<span class="md-footer-nav__direction">
Previous
</span>
Path Expressions
</span>
</div>
</a>
<a href="../prefix/" title="Prefix" class="md-flex md-footer-nav__link md-footer-nav__link--next" rel="next">
<div class="md-flex__cell md-flex__cell--stretch md-footer-nav__title">
<span class="md-flex__ellipsis">
<span class="md-footer-nav__direction">
Next
</span>
Prefix
</span>
</div>
<div class="md-flex__cell md-flex__cell--shrink">
<i class="md-icon md-icon--arrow-forward md-footer-nav__button"></i>
</div>
</a>
</nav>
</div>
<div class="md-footer-meta md-typeset">
<div class="md-footer-meta__inner md-grid">
<div class="md-footer-copyright">
powered by
<a href="https://www.mkdocs.org">MkDocs</a>
and
<a href="https://squidfunk.github.io/mkdocs-material/">
Material for MkDocs</a>
</div>
<div class="md-footer-social">
<link rel="stylesheet" href="../assets/fonts/font-awesome.css">
<a href="https://github.com/mikefarah" class="md-footer-social__link fa fa-github"></a>
<a href="https://www.linkedin.com/in/mike-farah-b5a75b2/" class="md-footer-social__link fa fa-linkedin"></a>
</div>
</div>
</div>
</footer>
</div>
<script src="../assets/javascripts/application.39abc4af.js"></script>
<script>app.initialize({version:"1.0.4",url:{base:".."}})</script>
</body>
</html>

8
examples/bad.yaml Normal file
View File

@@ -0,0 +1,8 @@
b:
d: be gone
c: 2
e:
- name: Billy Bob # comment over here
---
[123123

View File

@@ -4,4 +4,4 @@ c:
toast: leave
test: 1
tell: 1
taco: cool
tasty.taco: cool

View File

@@ -1,14 +1,4 @@
deep1:
hostA:
value: 1234
notRelevant:
value: bananas
hostB:
value: 5678
deep2:
hostC:
value: 1234
notRelevant:
value: bananas
hostD:
value: 5678
a: "simple" # just the best
b: [1, 3]
c:
test: 1

View File

@@ -1,13 +1,9 @@
bob:
item:
cats: bananas
something:
cats: lemons
itemThing:
cats: bananas
item2:
cats: apples
thing:
cats: oranges
my:
path: -3
a: true
b:
c: 2
d: [3, 4, 5]
e:
- name: fred
value: 3
- name: sam
value: 4

View File

@@ -1,4 +1,5 @@
foo: &foo
a: 1
foobar: *foo
foobar:
<<: *foo

17
go.mod
View File

@@ -1,13 +1,26 @@
module github.com/mikefarah/yq/v3
require (
github.com/mikefarah/yaml/v2 v2.4.0 // indirect
github.com/cosiner/argv v0.0.1 // indirect
github.com/go-delve/delve v1.4.0 // indirect
github.com/konsorten/go-windows-terminal-sequences v1.0.2 // indirect
github.com/kylelemons/godebug v1.1.0
github.com/mattn/go-colorable v0.1.4 // indirect
github.com/mattn/go-isatty v0.0.12 // indirect
github.com/mattn/go-runewidth v0.0.8 // indirect
github.com/peterh/liner v1.2.0 // indirect
github.com/pkg/errors v0.8.1
github.com/sirupsen/logrus v1.4.2 // indirect
github.com/spf13/cobra v0.0.5
github.com/spf13/pflag v1.0.5 // indirect
go.starlark.net v0.0.0-20200203144150-6677ee5c7211 // indirect
golang.org/x/arch v0.0.0-20191126211547-368ea8f32fff // indirect
golang.org/x/crypto v0.0.0-20200210222208-86ce3cb69678 // indirect
golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5 // indirect
golang.org/x/tools v0.0.0-20191213221258-04c2e8eff935 // indirect
gopkg.in/imdario/mergo.v0 v0.3.7 // indirect
gopkg.in/op/go-logging.v1 v1.0.0-20160211212156-b2cb9fa56473
gopkg.in/yaml.v3 v3.0.0-20191120175047-4206685974f2
gopkg.in/yaml.v3 v3.0.0-20200121175148-a6ecf24a6d71
)
go 1.13

88
go.sum
View File

@@ -1,15 +1,50 @@
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk=
github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
github.com/cosiner/argv v0.0.0-20170225145430-13bacc38a0a5 h1:rIXlvz2IWiupMFlC45cZCXZFvKX/ExBcSLrDy2G0Lp8=
github.com/cosiner/argv v0.0.0-20170225145430-13bacc38a0a5/go.mod h1:p/NrK5tF6ICIly4qwEDsf6VDirFiWWz0FenfYBwJaKQ=
github.com/cosiner/argv v0.0.1 h1:2iAFN+sWPktbZ4tvxm33Ei8VY66FPCxdOxpncUGpAXE=
github.com/cosiner/argv v0.0.1/go.mod h1:p/NrK5tF6ICIly4qwEDsf6VDirFiWWz0FenfYBwJaKQ=
github.com/cpuguy83/go-md2man v1.0.8/go.mod h1:N6JayAiVKtlHSnuTCeuLSQVs75hb8q+dYQLjr7cDsKY=
github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/go-delve/delve v1.4.0 h1:O+1dw1XBZXqhC6fIPQwGxLlbd2wDRau7NxNhVpw02ag=
github.com/go-delve/delve v1.4.0/go.mod h1:gQM0ReOJLNAvPuKAXfjHngtE93C2yc/ekTbo7YbAHSo=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM=
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/konsorten/go-windows-terminal-sequences v1.0.2 h1:DB17ag19krx9CFsz4o3enTrPXyIXCl+2iCXH/aMAp9s=
github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc=
github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
github.com/mattn/go-colorable v0.0.0-20170327083344-ded68f7a9561 h1:isR/L+BIZ+rqODWYR/f526ygrBMGKZYFhaaFRDGvuZ8=
github.com/mattn/go-colorable v0.0.0-20170327083344-ded68f7a9561/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
github.com/mattn/go-colorable v0.1.4 h1:snbPLB8fVfU9iwbbo30TPtbLRzwWu6aJS6Xh4eaaviA=
github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
github.com/mattn/go-isatty v0.0.3 h1:ns/ykhmWi7G9O+8a448SecJU3nSMBXJfqQkl0upE1jI=
github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY=
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
github.com/mattn/go-runewidth v0.0.3 h1:a+kO+98RDGEfo6asOGMmpodZq4FNtnGP54yps8BzLR4=
github.com/mattn/go-runewidth v0.0.3/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
github.com/mattn/go-runewidth v0.0.8 h1:3tS41NlGYSmhhe/8fhGRzc+z3AYCw1Fe1WAyLuujKs0=
github.com/mattn/go-runewidth v0.0.8/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
github.com/mikefarah/yaml v2.1.0+incompatible h1:nu2cqmzk4WlWJNgnevY88faMcdrDzYGcsUjYFxEpB7Y=
github.com/mikefarah/yaml/v2 v2.4.0 h1:eYqfooY0BnvKTJxr7+ABJs13n3dg9n347GScDaU2Lww=
github.com/mikefarah/yaml/v2 v2.4.0/go.mod h1:ahVqZF4n1W4NqwvVnZzC4es67xsW9uR/RRf2RRxieJU=
@@ -17,46 +52,99 @@ github.com/mikefarah/yq v2.4.0+incompatible h1:oBxbWy8R9hI3BIUUxEf0CzikWa2AgnGrG
github.com/mikefarah/yq/v2 v2.4.1 h1:tajDonaFK6WqitSZExB6fKlWQy/yCkptqxh2AXEe3N4=
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.8.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
github.com/peterh/liner v0.0.0-20170317030525-88609521dc4b h1:8uaXtUkxiy+T/zdLWuxa/PG4so0TPZDZfafFNNSaptE=
github.com/peterh/liner v0.0.0-20170317030525-88609521dc4b/go.mod h1:xIteQHvHuaLYG9IFj6mSxM0fCKrs34IrEQUhOYuGPHc=
github.com/peterh/liner v1.2.0 h1:w/UPXyl5GfahFxcTOz2j9wCIHNI+pUPr2laqpojKNCg=
github.com/peterh/liner v1.2.0/go.mod h1:CRroGNssyjTd/qIG2FyxByd2S8JEAZXBl4qUrZf8GS0=
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/profile v0.0.0-20170413231811-06b906832ed0/go.mod h1:hJw3o1OdXxsrSjjVksARp5W95eeEaEfptyVZyv6JUPA=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/russross/blackfriday v0.0.0-20180428102519-11635eb403ff/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
github.com/sirupsen/logrus v0.0.0-20180523074243-ea8897e79973 h1:3AJZYTzw3gm3TNTt30x0CCKD7GOn2sdd50Hn35fQkGY=
github.com/sirupsen/logrus v0.0.0-20180523074243-ea8897e79973/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc=
github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4=
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
github.com/spf13/cobra v0.0.0-20170417170307-b6cb39589372/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
github.com/spf13/cobra v0.0.5 h1:f0B+LkLX6DtmRH1isoNA9VTtNUK9K8xYd28JNNfOv/s=
github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU=
github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
github.com/spf13/pflag v0.0.0-20170417173400-9e4c21054fa1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
github.com/spf13/pflag v1.0.3 h1:zPAT6CGy6wXeQ7NtTnaTerfKOsV6V6F8agHXFiazDkg=
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0=
github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
go.starlark.net v0.0.0-20190702223751-32f345186213 h1:lkYv5AKwvvduv5XWP6szk/bvvgO6aDeUujhZQXIFTes=
go.starlark.net v0.0.0-20190702223751-32f345186213/go.mod h1:c1/X6cHgvdXj6pUlmWKMkuqRnW4K8x2vwt6JAaaircg=
go.starlark.net v0.0.0-20200203144150-6677ee5c7211 h1:Qoe+9POtDT51UBQ8XEnS9QKeHDQzEl2QRh3eok9R4aw=
go.starlark.net v0.0.0-20200203144150-6677ee5c7211/go.mod h1:nmDLcffg48OtT/PSW0Hg7FvpRQsQh5OSqIylirxKC7o=
golang.org/x/arch v0.0.0-20190927153633-4e8777c89be4 h1:QlVATYS7JBoZMVaf+cNjb90WD/beKVHnIxFKT4QaHVI=
golang.org/x/arch v0.0.0-20190927153633-4e8777c89be4/go.mod h1:flIaEI6LNU6xOCD5PaJvn9wGP0agmIOqjrtsKGRguv4=
golang.org/x/arch v0.0.0-20191126211547-368ea8f32fff h1:k/MrR0lKiCokRu1JUDDAWhWZinfBAOZRzz3LkPOkFMs=
golang.org/x/arch v0.0.0-20191126211547-368ea8f32fff/go.mod h1:flIaEI6LNU6xOCD5PaJvn9wGP0agmIOqjrtsKGRguv4=
golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550 h1:ObdrDkeb4kJdCP557AjRjq69pTHfNouLtWZG7j9rPN8=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200210222208-86ce3cb69678/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb h1:fgwFCsaw9buMuxNd6+DQfAuSFqbNiQZpcgJQAgJsK6k=
golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191002063906-3421d5a6bb1c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5 h1:LfCXLvNmTYH9kEmVgqbnsWfruoXZIrh4YBgqVHtDvw0=
golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/tools v0.0.0-20191030203535-5e247c9ad0a0 h1:s5lp4ug7qHzUccgyFdjsX7OZDzHXRaePrF3B3vmUiuM=
golang.org/x/tools v0.0.0-20191030203535-5e247c9ad0a0/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191127201027-ecd32218bd7f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191213221258-04c2e8eff935 h1:kJQZhwFzSwJS2BxboKjdZzWczQOZx8VuH7Y8hhuGUtM=
golang.org/x/tools v0.0.0-20191213221258-04c2e8eff935/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
gopkg.in/airbrake/gobrake.v2 v2.0.9/go.mod h1:/h5ZAUhDkGaJfjzjKLSjv6zCL6O0LLBxU4K+aSYdM/U=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
gopkg.in/gemnasium/logrus-airbrake-hook.v2 v2.1.2/go.mod h1:Xk6kEKp8OKb+X14hQBKWaSkCsqBpgog8nAV2xsGOxlo=
gopkg.in/imdario/mergo.v0 v0.3.7 h1:QDotlIZtaO/p+Um0ok18HRTpq5i5/SAk/qprsor+9c8=
gopkg.in/imdario/mergo.v0 v0.3.7/go.mod h1:9qPP6AGrlC1G2PTNXko614FwGZvorN7MiBU0Eppok+U=
gopkg.in/op/go-logging.v1 v1.0.0-20160211212156-b2cb9fa56473 h1:6D+BvnJ/j6e222UW8s2qTSe3wGBtvo0MbVQG/c5k8RE=
gopkg.in/op/go-logging.v1 v1.0.0-20160211212156-b2cb9fa56473/go.mod h1:N1eN2tsCx0Ydtgjl4cqmbRCsY4/+z4cYDeqwZTk6zog=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10=
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v3 v3.0.0-20191120175047-4206685974f2 h1:XZx7nhd5GMaZpmDaEHFVafUZC7ya0fuo7cSJ3UCKYmM=
gopkg.in/yaml.v3 v3.0.0-20191120175047-4206685974f2/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0-20200121175148-a6ecf24a6d71 h1:Xe2gvTZUJpsvOWUnvmL/tmhVBZUmHSvLbMjRj6NUUKo=
gopkg.in/yaml.v3 v3.0.0-20200121175148-a6ecf24a6d71/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4=

View File

@@ -2,28 +2,6 @@ docs_dir: mkdocs
site_dir: docs
site_name: Yq
theme: 'material'
pages:
- Install: index.md
- Read: read.md
- Path Expressions: path_expressions.md
- Write/Update: write.md
- Prefix: prefix.md
- Delete: delete.md
- Create: create.md
- Convert: convert.md
- Merge: merge.md
repo_name: 'mikefarah/yq'
repo_url: 'https://github.com/mikefarah/yq'
extra:
social:
- type: 'github'
link: 'https://github.com/mikefarah'
- type: 'linkedin'
link: 'https://www.linkedin.com/in/mike-farah-b5a75b2/'
markdown_extensions:
- markdown_include.include:
base_path: mkdocs
- toc:
permalink: True

View File

@@ -1,60 +0,0 @@
## Yaml to Json
To convert output to json, use the --tojson (or -j) flag. This is supported by all commands.
Each matching yaml node will be converted to json and printed out on a separate line.
Given a sample.yaml file of:
```yaml
b:
c: 2
```
then
```bash
yq r -j sample.yaml
```
will output
```json
{"b":{"c":2}}
```
Given a sample.yaml file of:
```yaml
bob:
c: 2
bab:
c: 5
```
then
```bash
yq r -j sample.yaml b*
```
will output
```json
{"c":2}
{"c":5}
```
## Json to Yaml
To read in json, just pass in a json file instead of yaml, it will just work :)
e.g given a json file
```json
{"a":"Easy! as one two three","b":{"c":2,"d":[3,4]}}
```
then
```bash
yq r sample.json
```
will output
```yaml
a: Easy! as one two three
b:
c: 2
d:
- 3
- 4
```

View File

@@ -1,47 +0,0 @@
```
yq n <path_expression> <new value>
```
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.
See docs for [path expression](path_expressions.md)
## Creating a simple yaml file
```bash
yq n b.c cat
```
will output:
```yaml
b:
c: cat
```
## Creating using a create script
Create scripts follow the same format as the update scripts.
Given a script create_instructions.yaml of:
```yaml
- command: update
path: b.c
value:
#great
things: frog # wow!
```
then
```bash
yq n -s create_instructions.yaml
```
will output:
```yaml
b:
c:
#great
things: frog # wow!
```
You can also pipe the instructions in:
```bash
cat create_instructions.yaml | yq n -s -
```

View File

@@ -1,86 +0,0 @@
```
yq delete <yaml_file|-> <path_expression>
```
The delete command will delete all the matching nodes for the path expression in the given yaml input.
See docs for [path expression](path_expressions.md) for more details.
## Deleting from a simple document
Given a sample.yaml file of:
```yaml
b:
c: 2
apples: green
```
then
```bash
yq d sample.yaml b.c
```
will output
```yaml
b:
apples: green
```
## From STDIN
Use "-" (without quotes) in-place of a file name if you wish to pipe in input from STDIN.
```bash
cat sample.yaml | yq d - b.c
```
## Deleting in-place
```bash
yq d -i sample.yaml b.c
```
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
```
### 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
```

View File

@@ -1,26 +0,0 @@
# yq
yq is a lightweight and portable command-line YAML processor
The aim of the project is to be the [jq](https://github.com/stedolan/jq) or sed of yaml files.
## Install
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
sudo apt update
sudo apt install yq -y
```
or, [Download latest binary](https://github.com/mikefarah/yq/releases/latest) or alternatively:
```
GO111MODULE=on go get github.com/mikefarah/yq/v3
```
[View on GitHub](https://github.com/mikefarah/yq)

View File

@@ -1,176 +0,0 @@
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.
```
yq m <yaml_file> <path>...
```
## Merge example
Given a data1.yaml file of:
```yaml
a: simple
b: [1, 2]
```
and data2.yaml file of:
```yaml
a: other
c:
test: 1
```
then
```bash
yq m data1.yaml data2.yaml
```
will output:
```yaml
a: simple
b: [1, 2]
c:
test: 1
```
## Updating files in-place
```bash
yq m -i data1.yaml data2.yaml
```
will update the data1.yaml file with the merged result.
## Overwrite values
Given a data1.yaml file of:
```yaml
a: simple
b: [1, 2]
```
and data2.yaml file of:
```yaml
a: other
c:
test: 1
```
then
```bash
yq m -x data1.yaml data2.yaml
```
will output:
```yaml
a: other
b: [1, 2]
c:
test: 1
```
### Overwrite values with arrays
Given a data1.yaml file of:
```yaml
a: simple
b: [1, 2]
```
and data3.yaml file of:
```yaml
b: [3, 4]
c:
test: 2
other: true
d: false
```
then
```bash
yq m -x data1.yaml data3.yaml
```
will output:
```yaml
a: simple
b: [3, 4]
c:
test: 2
other: true
d: false
```
Notice that 'b' does not result in the merging of the values within an array.
## Append values with arrays
Given a data1.yaml file of:
```yaml
a: simple
b: [1, 2]
d: hi
```
and data3.yaml file of:
```yaml
a: something
b: [3, 4]
c:
test: 2
other: true
```
then
```bash
yq m -a data1.yaml data3.yaml
```
will output:
```yaml
a: simple
b: [1, 2, 3, 4]
c:
test: 2
other: true
d: hi
```
Note that the 'b' array has concatenated the values from the second data file. Also note that other map keys are not overridden (field a).
## 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
```
### 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
```

View File

@@ -1,208 +0,0 @@
Path expressions are used to deeply navigate and match particular yaml nodes.
_As a general rule, you should wrap paths in quotes to prevent your CLI from processing '*, []' and other special characters._
## Simple expressions
### Maps
a.b.c
```yaml
a:
b:
c: thing # MATCHES
```
### Arrays
a.b[1].c
```yaml
a:
b:
- c: thing0
- c: thing1 # MATCHES
- c: thing2
```
#### Appending to arrays
(e.g. when using the write command)
a.b[+].c
```yaml
a:
b:
- c: thing0
```
Will add a new entry:
```yaml
a:
b:
- c: thing0
- c: thing1 # NEW entry from [+] on B array.
```
## Splat
### Maps
a.*.c
```yaml
a:
b1:
c: thing # MATCHES
d: whatever
b2:
c: thing # MATCHES
f: something irrelevant
```
#### Prefix splat
bob.item*.cats
```yaml
bob:
item:
cats: bananas # MATCHES
something:
cats: lemons
itemThing:
cats: more bananas # MATCHES
item2:
cats: apples # MATCHES
thing:
cats: oranges
```
### Arrays
a.b[*].c
```yaml
a:
b:
- c: thing0 # MATCHES
d: what..ever
- c: thing1 # MATCHES
d: blarh
- c: thing2 # MATCHES
f: thingamabob
```
## Deep Splat
'**' will match arbitrary nodes for both maps and arrays:
a.**.c
```yaml
a:
b1:
c: thing1 # MATCHES
d: cat cat
b2:
c: thing2 # MATCHES
d: dog dog
b3:
d:
- f:
c: thing3 # MATCHES
d: beep
- f:
g:
c: thing4 # MATCHES
d: boop
- d: mooo
```
## Search by children nodes
a.(b.d==cat).b.c
```yaml
a:
- b:
c: thing0
d: leopard
ba: fast
- b:
c: thing1 # MATCHES
d: cat
ba: meowy
- b:
c: thing2
d: caterpillar
ba: icky
- b:
c: thing3 # MATCHES
d: cat
ba: also meowy
```
### With prefixes
a.(b.d==cat*).c
```yaml
a:
- b:
c: thing0
d: leopard
ba: fast
- b:
c: thing1 # MATCHES
d: cat
ba: meowy
- b:
c: thing2 # MATCHES
d: caterpillar
ba: icky
- b:
c: thing3 # MATCHES
d: cat
ba: also meowy
```
## Special Characters
### Keys with dots
When specifying a key that has a dot use key lookup indicator.
```yaml
b:
foo.bar: 7
```
```bash
yaml r sample.yaml 'b[foo.bar]'
```
```bash
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.
### Keys (and values) with leading dashes
The flag terminator needs to be used to stop the app from attempting to parse the subsequent arguments as flags, if they start if a dash.
```bash
yq n -j -- --key --value
```
Will result in
```
--key: --value
```

View File

@@ -1,75 +0,0 @@
```
yq p <yaml_file> <path>
```
Prefixes a yaml document with the given path expression. The complete yaml content will be nested inside the new prefix path.
See docs for [path expression](path_expressions.md) for more details.
## Prefix a document
Given a data1.yaml file of:
```yaml
a:
b: [1, 2]
```
then
```bash
yq p data1.yaml c.d
```
will output:
```yaml
c:
d:
a:
b: [1, 2]
```
## Updating files in-place
```bash
yq p -i data1.yaml c
```
will update the data1.yaml file so that the path 'c' prefixes the document.
## Multiple Documents
### Prefix a single document
Given a data1.yaml file of:
```yaml
something: else
---
a: simple
b: cat
```
then
```bash
yq p -d1 data1.yaml c
```
will output:
```yaml
something: else
---
c:
a: simple
b: cat
```
### Prefix all documents
Given a data1.yaml file of:
```yaml
something: else
---
a: simple
b: cat
```
then
```bash
yq p -d'*' data1.yaml c
```
will output:
```yaml
c:
something: else
---
c:
a: simple
b: cat
```

View File

@@ -1,69 +0,0 @@
```
yq r <yaml_file|json_file> <path_expression>
```
TALK PRINTING ABOUT KEYS AND VALUES
Returns the matching nodes of the path expression for the given yaml file (or STDIN).
See docs for [path expression](path_expressions.md) for more details.
## Basic
Given a sample.yaml file of:
```yaml
b:
c: 2
```
then
```bash
yq r sample.yaml b.c
```
will output the value of '2'.
## From Stdin
Given a sample.yaml file of:
```bash
cat sample.yaml | yq r - b.c
```
will output the value of '2'.
## Multiple Documents
### Reading from a single document
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'.
### Read from all documents
Reading all documents will return the result as an array. This can be converted to json using the '-j' flag if desired.
Given a sample.yaml file of:
```yaml
name: Fred
age: 22
---
name: Stella
age: 23
---
name: Android
age: 232
```
then
```bash
yq r -d'*' sample.yaml name
```
will output:
```
- Fred
- Stella
- Android
```

View File

@@ -1,157 +0,0 @@
```
yq w <yaml_file> <path_expression> <new value>
```
Updates all the matching nodes of path expression to the supplied value.
See docs for [path expression](path_expressions.md) for more details.
## Basic
Given a sample.yaml file of:
```yaml
b:
c: 2
```
then
```bash
yq w sample.yaml b.c cat
```
will output:
```yaml
b:
c: cat
```
### Updating files in-place
```bash
yq w -i sample.yaml b.c cat
```
will update the sample.yaml file so that the value of 'c' is cat.
## From STDIN
```bash
cat sample.yaml | yq w - b.c blah
```
## Adding new fields
Any missing fields in the path will be created on the fly.
Given a sample.yaml file of:
```yaml
b:
c: 2
```
then
```bash
yq w sample.yaml b.d[+] "new thing"
```
will output:
```yaml
b:
c: cat
d:
- new thing
```
## Appending value to an array field
Given a sample.yaml file of:
```yaml
b:
c: 2
d:
- new thing
- foo thing
```
then
```bash
yq w sample.yaml "b.d[+]" "bar thing"
```
will output:
```yaml
b:
c: cat
d:
- new thing
- foo thing
- bar thing
```
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
```
### 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
```
UPDATE THIS
UPDATE THIS
INCLUDE DELETE EXAMPLE
## Updating multiple values with a script
Given a sample.yaml file of:
```yaml
b:
c: 2
e:
- name: Billy Bob
```
and a script update_instructions.yaml of:
```yaml
b.c: 3
b.e[+].name: Howdy Partner
```
then
```bash
yq w -s update_instructions.yaml sample.yaml
```
will output:
```yaml
b:
c: 3
e:
- name: Howdy Partner
```
And, of course, you can pipe the instructions in using '-':
```bash
cat update_instructions.yaml | yq w -s - sample.yaml
```

View File

@@ -1,14 +1,14 @@
package yqlib
import (
"fmt"
"strconv"
errors "github.com/pkg/errors"
yaml "gopkg.in/yaml.v3"
)
type DataNavigator interface {
Traverse(value *yaml.Node, path []string) error
Traverse(value *yaml.Node, path []interface{}) error
}
type navigator struct {
@@ -21,7 +21,7 @@ func NewDataNavigator(NavigationStrategy NavigationStrategy) DataNavigator {
}
}
func (n *navigator) Traverse(value *yaml.Node, path []string) error {
func (n *navigator) Traverse(value *yaml.Node, path []interface{}) error {
realValue := value
emptyArray := make([]interface{}, 0)
if realValue.Kind == yaml.DocumentNode {
@@ -31,12 +31,17 @@ func (n *navigator) Traverse(value *yaml.Node, path []string) error {
return n.doTraverse(value, "", path, emptyArray)
}
func (n *navigator) doTraverse(value *yaml.Node, head string, tail []string, pathStack []interface{}) error {
func (n *navigator) doTraverse(value *yaml.Node, head interface{}, tail []interface{}, pathStack []interface{}) error {
log.Debug("head %v", head)
DebugNode(value)
var nodeContext = NewNodeContext(value, head, tail, pathStack)
var errorDeepSplatting error
if head == "**" && value.Kind != yaml.ScalarNode {
errorDeepSplatting = n.recurse(value, head, tail, pathStack)
if head == "**" && value.Kind != yaml.ScalarNode && n.navigationStrategy.ShouldDeeplyTraverse(nodeContext) {
if len(pathStack) == 0 || pathStack[len(pathStack)-1] != "<<" {
errorDeepSplatting = n.recurse(value, head, tail, pathStack)
}
// ignore errors here, we are deep splatting so we may accidently give a string key
// to an array sequence
if len(tail) > 0 {
@@ -45,36 +50,45 @@ func (n *navigator) doTraverse(value *yaml.Node, head string, tail []string, pat
return errorDeepSplatting
}
if len(tail) > 0 {
if len(tail) > 0 && value.Kind != yaml.ScalarNode {
log.Debugf("diving into %v", tail[0])
DebugNode(value)
return n.recurse(value, tail[0], tail[1:], pathStack)
}
return n.navigationStrategy.Visit(NewNodeContext(value, head, tail, pathStack))
return n.navigationStrategy.Visit(nodeContext)
}
func (n *navigator) getOrReplace(original *yaml.Node, expectedKind yaml.Kind) *yaml.Node {
if original.Kind != expectedKind {
log.Debug("wanted %v but it was %v, overriding", expectedKind, original.Kind)
log.Debug("wanted %v but it was %v, overriding", KindString(expectedKind), KindString(original.Kind))
return &yaml.Node{Kind: expectedKind}
}
return original
}
func (n *navigator) recurse(value *yaml.Node, head string, tail []string, pathStack []interface{}) error {
log.Debug("recursing, processing %v", head)
func (n *navigator) recurse(value *yaml.Node, head interface{}, tail []interface{}, pathStack []interface{}) error {
log.Debug("recursing, processing %v, pathStack %v", head, pathStackToString(pathStack))
switch value.Kind {
case yaml.MappingNode:
log.Debug("its a map with %v entries", len(value.Content)/2)
return n.recurseMap(value, head, tail, pathStack)
headString := fmt.Sprintf("%v", head)
return n.recurseMap(value, headString, tail, pathStack)
case yaml.SequenceNode:
log.Debug("its a sequence of %v things!", len(value.Content))
if n.navigationStrategy.GetPathParser().IsPathExpression(head) {
switch head := head.(type) {
case int64:
return n.recurseArray(value, head, head, tail, pathStack)
default:
if head == "+" {
return n.appendArray(value, head, tail, pathStack)
} else if len(value.Content) == 0 && head == "**" {
return n.navigationStrategy.Visit(NewNodeContext(value, head, tail, pathStack))
}
return n.splatArray(value, head, tail, pathStack)
} else if head == "+" {
return n.appendArray(value, head, tail, pathStack)
}
return n.recurseArray(value, head, tail, pathStack)
case yaml.AliasNode:
log.Debug("its an alias!")
DebugNode(value.Alias)
@@ -84,24 +98,22 @@ func (n *navigator) recurse(value *yaml.Node, head string, tail []string, pathSt
}
return nil
default:
return nil
return n.navigationStrategy.Visit(NewNodeContext(value, head, tail, pathStack))
}
}
func (n *navigator) recurseMap(value *yaml.Node, head string, tail []string, pathStack []interface{}) error {
func (n *navigator) recurseMap(value *yaml.Node, head string, tail []interface{}, pathStack []interface{}) error {
traversedEntry := false
errorVisiting := n.visitMatchingEntries(value, head, tail, pathStack, func(contents []*yaml.Node, indexInMap int) error {
log.Debug("recurseMap: visitMatchingEntries")
log.Debug("recurseMap: visitMatchingEntries for %v", contents[indexInMap].Value)
n.navigationStrategy.DebugVisitedNodes()
newPathStack := append(pathStack, contents[indexInMap].Value)
log.Debug("appended %v", contents[indexInMap].Value)
n.navigationStrategy.DebugVisitedNodes()
log.Debug("should I traverse? head: %v, path: %v", head, pathStackToString(newPathStack))
DebugNode(value)
if n.navigationStrategy.ShouldTraverse(NewNodeContext(contents[indexInMap+1], head, tail, newPathStack), contents[indexInMap].Value) {
log.Debug("recurseMap: Going to traverse")
traversedEntry = true
// contents[indexInMap+1] = n.getOrReplace(contents[indexInMap+1], guessKind(head, tail, contents[indexInMap+1].Kind))
contents[indexInMap+1] = n.getOrReplace(contents[indexInMap+1], guessKind(head, tail, contents[indexInMap+1].Kind))
errorTraversing := n.doTraverse(contents[indexInMap+1], head, tail, newPathStack)
log.Debug("recurseMap: Finished traversing")
n.navigationStrategy.DebugVisitedNodes()
@@ -116,22 +128,33 @@ func (n *navigator) recurseMap(value *yaml.Node, head string, tail []string, pat
return errorVisiting
}
if traversedEntry || n.navigationStrategy.GetPathParser().IsPathExpression(head) || !n.navigationStrategy.AutoCreateMap(NewNodeContext(value, head, tail, pathStack)) {
if len(value.Content) == 0 && head == "**" {
return n.navigationStrategy.Visit(NewNodeContext(value, head, tail, pathStack))
} else if traversedEntry || n.navigationStrategy.GetPathParser().IsPathExpression(head) || !n.navigationStrategy.AutoCreateMap(NewNodeContext(value, head, tail, pathStack)) {
return nil
}
_, errorParsingInt := strconv.ParseInt(head, 10, 64)
mapEntryKey := yaml.Node{Value: head, Kind: yaml.ScalarNode}
if errorParsingInt == nil {
// fixes a json encoding problem where keys that look like numbers
// get treated as numbers and cannot be used in a json map
mapEntryKey.Style = yaml.LiteralStyle
}
value.Content = append(value.Content, &mapEntryKey)
mapEntryValue := yaml.Node{Kind: guessKind(head, tail, 0)}
value.Content = append(value.Content, &mapEntryValue)
log.Debug("adding new node %v", head)
log.Debug("adding a new node %v - def a string", head)
return n.doTraverse(&mapEntryValue, head, tail, append(pathStack, head))
}
// need to pass the node in, as it may be aliased
type mapVisitorFn func(contents []*yaml.Node, index int) error
func (n *navigator) visitDirectMatchingEntries(node *yaml.Node, head string, tail []string, pathStack []interface{}, visit mapVisitorFn) error {
func (n *navigator) visitDirectMatchingEntries(node *yaml.Node, head string, tail []interface{}, pathStack []interface{}, visit mapVisitorFn) error {
var contents = node.Content
for index := 0; index < len(contents); index = index + 2 {
content := contents[index]
@@ -146,7 +169,7 @@ func (n *navigator) visitDirectMatchingEntries(node *yaml.Node, head string, tai
return nil
}
func (n *navigator) visitMatchingEntries(node *yaml.Node, head string, tail []string, pathStack []interface{}, visit mapVisitorFn) error {
func (n *navigator) visitMatchingEntries(node *yaml.Node, head string, tail []interface{}, pathStack []interface{}, visit mapVisitorFn) error {
var contents = node.Content
log.Debug("visitMatchingEntries %v", head)
DebugNode(node)
@@ -162,17 +185,17 @@ func (n *navigator) visitMatchingEntries(node *yaml.Node, head string, tail []st
return n.visitAliases(contents, head, tail, pathStack, visit)
}
func (n *navigator) visitAliases(contents []*yaml.Node, head string, tail []string, pathStack []interface{}, visit mapVisitorFn) error {
func (n *navigator) visitAliases(contents []*yaml.Node, head string, tail []interface{}, pathStack []interface{}, visit mapVisitorFn) error {
// merge aliases are defined first, but we only want to traverse them
// if we don't find a match on this node first.
// traverse them backwards so that the last alias overrides the preceding.
// a node can either be
// an alias to one other node (e.g. <<: *blah)
// or a sequence of aliases (e.g. <<: [*blah, *foo])
log.Debug("checking for aliases")
log.Debug("checking for aliases, head: %v, pathstack: %v", head, pathStackToString(pathStack))
for index := len(contents) - 2; index >= 0; index = index - 2 {
if contents[index+1].Kind == yaml.AliasNode {
if contents[index+1].Kind == yaml.AliasNode && contents[index].Value == "<<" {
valueNode := contents[index+1]
log.Debug("found an alias")
DebugNode(contents[index])
@@ -193,7 +216,7 @@ func (n *navigator) visitAliases(contents []*yaml.Node, head string, tail []stri
return nil
}
func (n *navigator) visitAliasSequence(possibleAliasArray []*yaml.Node, head string, tail []string, pathStack []interface{}, visit mapVisitorFn) error {
func (n *navigator) visitAliasSequence(possibleAliasArray []*yaml.Node, head string, tail []interface{}, pathStack []interface{}, visit mapVisitorFn) error {
// need to search this backwards too, so that aliases defined last override the preceding.
for aliasIndex := len(possibleAliasArray) - 1; aliasIndex >= 0; aliasIndex = aliasIndex - 1 {
child := possibleAliasArray[aliasIndex]
@@ -209,7 +232,7 @@ func (n *navigator) visitAliasSequence(possibleAliasArray []*yaml.Node, head str
return nil
}
func (n *navigator) splatArray(value *yaml.Node, head string, tail []string, pathStack []interface{}) error {
func (n *navigator) splatArray(value *yaml.Node, head interface{}, tail []interface{}, pathStack []interface{}) error {
for index, childValue := range value.Content {
log.Debug("processing")
DebugNode(childValue)
@@ -217,6 +240,9 @@ func (n *navigator) splatArray(value *yaml.Node, head string, tail []string, pat
newPathStack := append(pathStack, index)
if n.navigationStrategy.ShouldTraverse(NewNodeContext(childValue, head, tail, newPathStack), childValue.Value) {
// here we should not deeply traverse the array if we are appending..not sure how to do that.
// need to visit instead...
// easiest way is to pop off the head and pass the rest of the tail in.
var err = n.doTraverse(childValue, head, tail, newPathStack)
if err != nil {
return err
@@ -226,19 +252,14 @@ func (n *navigator) splatArray(value *yaml.Node, head string, tail []string, pat
return nil
}
func (n *navigator) appendArray(value *yaml.Node, head string, tail []string, pathStack []interface{}) error {
func (n *navigator) appendArray(value *yaml.Node, head interface{}, tail []interface{}, pathStack []interface{}) error {
var newNode = yaml.Node{Kind: guessKind(head, tail, 0)}
value.Content = append(value.Content, &newNode)
log.Debug("appending a new node, %v", value.Content)
return n.doTraverse(&newNode, head, tail, append(pathStack, len(value.Content)-1))
}
func (n *navigator) recurseArray(value *yaml.Node, head string, tail []string, pathStack []interface{}) error {
var index, err = strconv.ParseInt(head, 10, 64) // nolint
if err != nil {
return errors.Wrapf(err, "Error parsing array index '%v' for '%v'", head, pathStackToString(pathStack))
}
func (n *navigator) recurseArray(value *yaml.Node, index int64, head interface{}, tail []interface{}, pathStack []interface{}) error {
for int64(len(value.Content)) <= index {
value.Content = append(value.Content, &yaml.Node{Kind: guessKind(head, tail, 0)})
}

View File

@@ -1,12 +1,10 @@
package yqlib
import (
"strconv"
yaml "gopkg.in/yaml.v3"
)
func DeleteNavigationStrategy(pathElementToDelete string) NavigationStrategy {
func DeleteNavigationStrategy(pathElementToDelete interface{}) NavigationStrategy {
parser := NewPathParser()
return &NavigationStrategyImpl{
visitedNodes: []*NodeContext{},
@@ -15,6 +13,9 @@ func DeleteNavigationStrategy(pathElementToDelete string) NavigationStrategy {
return false
},
autoCreateMap: func(nodeContext NodeContext) bool {
return false
},
shouldDeeplyTraverse: func(nodeContext NodeContext) bool {
return true
},
visit: func(nodeContext NodeContext) error {
@@ -22,10 +23,7 @@ func DeleteNavigationStrategy(pathElementToDelete string) NavigationStrategy {
log.Debug("need to find and delete %v in here", pathElementToDelete)
DebugNode(node)
if node.Kind == yaml.SequenceNode {
newContent, errorDeleting := deleteFromArray(node.Content, pathElementToDelete)
if errorDeleting != nil {
return errorDeleting
}
newContent := deleteFromArray(parser, node.Content, nodeContext.PathStack, pathElementToDelete)
node.Content = newContent
} else if node.Kind == yaml.MappingNode {
node.Content = deleteFromMap(parser, node.Content, nodeContext.PathStack, pathElementToDelete)
@@ -34,12 +32,12 @@ func DeleteNavigationStrategy(pathElementToDelete string) NavigationStrategy {
},
}
}
func deleteFromMap(pathParser PathParser, contents []*yaml.Node, pathStack []interface{}, pathElementToDelete string) []*yaml.Node {
func deleteFromMap(pathParser PathParser, contents []*yaml.Node, pathStack []interface{}, pathElementToDelete interface{}) []*yaml.Node {
newContents := make([]*yaml.Node, 0)
for index := 0; index < len(contents); index = index + 2 {
keyNode := contents[index]
valueNode := contents[index+1]
if !pathParser.MatchesNextPathElement(NewNodeContext(keyNode, pathElementToDelete, []string{}, pathStack), keyNode.Value) {
if !pathParser.MatchesNextPathElement(NewNodeContext(keyNode, pathElementToDelete, make([]interface{}, 0), pathStack), keyNode.Value) {
log.Debug("adding node %v", keyNode.Value)
newContents = append(newContents, keyNode, valueNode)
} else {
@@ -49,19 +47,30 @@ func deleteFromMap(pathParser PathParser, contents []*yaml.Node, pathStack []int
return newContents
}
func deleteFromArray(content []*yaml.Node, pathElementToDelete string) ([]*yaml.Node, error) {
func deleteFromArray(pathParser PathParser, content []*yaml.Node, pathStack []interface{}, pathElementToDelete interface{}) []*yaml.Node {
if pathElementToDelete == "*" {
return make([]*yaml.Node, 0), nil
switch pathElementToDelete := pathElementToDelete.(type) {
case int64:
return deleteIndexInArray(content, pathElementToDelete)
default:
log.Debug("%v is not a numeric index, finding matching patterns", pathElementToDelete)
var newArray = make([]*yaml.Node, 0)
for _, childValue := range content {
if !pathParser.MatchesNextPathElement(NewNodeContext(childValue, pathElementToDelete, make([]interface{}, 0), pathStack), childValue.Value) {
newArray = append(newArray, childValue)
}
}
return newArray
}
var index, err = strconv.ParseInt(pathElementToDelete, 10, 64) // nolint
if err != nil {
return content, err
}
}
func deleteIndexInArray(content []*yaml.Node, index int64) []*yaml.Node {
log.Debug("deleting index %v in array", index)
if index >= int64(len(content)) {
log.Debug("index %v is greater than content length %v", index, len(content))
return content, nil
return content
}
return append(content[:index], content[index+1:]...), nil
return append(content[:index], content[index+1:]...)
}

View File

@@ -15,9 +15,12 @@ type yamlEncoder struct {
encoder *yaml.Encoder
}
func NewYamlEncoder(destination io.Writer) Encoder {
func NewYamlEncoder(destination io.Writer, indent int) Encoder {
var encoder = yaml.NewEncoder(destination)
encoder.SetIndent(2)
if indent < 0 {
indent = 0
}
encoder.SetIndent(indent)
return &yamlEncoder{encoder}
}
@@ -29,8 +32,16 @@ type jsonEncoder struct {
encoder *json.Encoder
}
func NewJsonEncoder(destination io.Writer) Encoder {
func NewJsonEncoder(destination io.Writer, prettyPrint bool, indent int) Encoder {
var encoder = json.NewEncoder(destination)
var indentString = ""
for index := 0; index < indent; index++ {
indentString = indentString + " "
}
if prettyPrint {
encoder.SetIndent("", indentString)
}
return &jsonEncoder{encoder}
}

View File

@@ -19,6 +19,23 @@ type UpdateCommand struct {
Overwrite bool
}
func KindString(kind yaml.Kind) string {
switch kind {
case yaml.ScalarNode:
return "ScalarNode"
case yaml.SequenceNode:
return "SequenceNode"
case yaml.MappingNode:
return "MappingNode"
case yaml.DocumentNode:
return "DocumentNode"
case yaml.AliasNode:
return "AliasNode"
default:
return "unknown!"
}
}
func DebugNode(value *yaml.Node) {
if value == nil {
log.Debug("-- node is nil --")
@@ -30,7 +47,7 @@ func DebugNode(value *yaml.Node) {
log.Error("Error debugging node, %v", errorEncoding.Error())
}
encoder.Close()
log.Debug("Tag: %v", value.Tag)
log.Debug("Tag: %v, Kind: %v", value.Tag, KindString(value.Kind))
log.Debug("%v", buf.String())
}
}
@@ -43,7 +60,7 @@ func mergePathStackToString(pathStack []interface{}, appendArrays bool) string {
var sb strings.Builder
for index, path := range pathStack {
switch path.(type) {
case int:
case int, int64:
if appendArrays {
sb.WriteString("[+]")
} else {
@@ -51,45 +68,71 @@ func mergePathStackToString(pathStack []interface{}, appendArrays bool) string {
}
default:
sb.WriteString(fmt.Sprintf("%v", path))
s := fmt.Sprintf("%v", path)
var _, errParsingInt = strconv.ParseInt(s, 10, 64) // nolint
hasSpecial := strings.Contains(s, ".") || strings.Contains(s, "[") || strings.Contains(s, "]") || strings.Contains(s, "\"")
hasDoubleQuotes := strings.Contains(s, "\"")
wrappingCharacterStart := "\""
wrappingCharacterEnd := "\""
if hasDoubleQuotes {
wrappingCharacterStart = "("
wrappingCharacterEnd = ")"
}
if hasSpecial || errParsingInt == nil {
sb.WriteString(wrappingCharacterStart)
}
sb.WriteString(s)
if hasSpecial || errParsingInt == nil {
sb.WriteString(wrappingCharacterEnd)
}
}
if index < len(pathStack)-1 {
sb.WriteString(".")
}
}
return sb.String()
var pathString = sb.String()
log.Debug("got a path string: %v", pathString)
return pathString
}
func guessKind(head string, tail []string, guess yaml.Kind) yaml.Kind {
log.Debug("tail %v", tail)
func guessKind(head interface{}, tail []interface{}, guess yaml.Kind) yaml.Kind {
log.Debug("guessKind: tail %v", tail)
if len(tail) == 0 && guess == 0 {
log.Debug("end of path, must be a scalar")
return yaml.ScalarNode
} else if len(tail) == 0 {
return guess
}
var _, errorParsingInt = strconv.ParseInt(tail[0], 10, 64)
if tail[0] == "+" || errorParsingInt == nil {
var next = tail[0]
switch next.(type) {
case int64:
return yaml.SequenceNode
default:
var nextString = fmt.Sprintf("%v", next)
if nextString == "+" {
return yaml.SequenceNode
}
pathParser := NewPathParser()
if pathParser.IsPathExpression(nextString) && (guess == yaml.SequenceNode || guess == yaml.MappingNode) {
return guess
} else if guess == yaml.AliasNode {
log.Debug("guess was an alias, okey doke.")
return guess
} else if head == "**" {
log.Debug("deep wildcard, go with the guess")
return guess
}
log.Debug("forcing a mapping node")
log.Debug("yaml.SequenceNode %v", guess == yaml.SequenceNode)
log.Debug("yaml.ScalarNode %v", guess == yaml.ScalarNode)
return yaml.MappingNode
}
pathParser := NewPathParser()
if (pathParser.IsPathExpression(tail[0]) || head == "**") && (guess == yaml.SequenceNode || guess == yaml.MappingNode) {
return guess
}
if guess == yaml.AliasNode {
log.Debug("guess was an alias, okey doke.")
return guess
}
log.Debug("forcing a mapping node")
log.Debug("yaml.SequenceNode %v", guess == yaml.SequenceNode)
log.Debug("yaml.ScalarNode %v", guess == yaml.ScalarNode)
return yaml.MappingNode
}
type YqLib interface {
Get(rootNode *yaml.Node, path string) ([]*NodeContext, error)
Get(rootNode *yaml.Node, path string, deeplyTraverseArrays bool) ([]*NodeContext, error)
Update(rootNode *yaml.Node, updateCommand UpdateCommand, autoCreate bool) error
New(path string) yaml.Node
@@ -107,9 +150,9 @@ func NewYqLib() YqLib {
}
}
func (l *lib) Get(rootNode *yaml.Node, path string) ([]*NodeContext, error) {
func (l *lib) Get(rootNode *yaml.Node, path string, deeplyTraverseArrays bool) ([]*NodeContext, error) {
var paths = l.parser.ParsePath(path)
navigationStrategy := ReadNavigationStrategy()
navigationStrategy := ReadNavigationStrategy(deeplyTraverseArrays)
navigator := NewDataNavigator(navigationStrategy)
error := navigator.Traverse(rootNode, paths)
return navigationStrategy.GetVisitedNodes(), error

View File

@@ -8,13 +8,13 @@ import (
type NodeContext struct {
Node *yaml.Node
Head string
Tail []string
Head interface{}
Tail []interface{}
PathStack []interface{}
}
func NewNodeContext(node *yaml.Node, head string, tail []string, pathStack []interface{}) NodeContext {
newTail := make([]string, len(tail))
func NewNodeContext(node *yaml.Node, head interface{}, tail []interface{}, pathStack []interface{}) NodeContext {
newTail := make([]interface{}, len(tail))
copy(newTail, tail)
newPathStack := make([]interface{}, len(pathStack))
@@ -34,18 +34,20 @@ type NavigationStrategy interface {
// node key is the string value of the last element in the path stack
// we use it to match against the pathExpression in head.
ShouldTraverse(nodeContext NodeContext, nodeKey string) bool
ShouldDeeplyTraverse(nodeContext NodeContext) bool
GetVisitedNodes() []*NodeContext
DebugVisitedNodes()
GetPathParser() PathParser
}
type NavigationStrategyImpl struct {
followAlias func(nodeContext NodeContext) bool
autoCreateMap func(nodeContext NodeContext) bool
visit func(nodeContext NodeContext) error
shouldVisitExtraFn func(nodeContext NodeContext) bool
visitedNodes []*NodeContext
pathParser PathParser
followAlias func(nodeContext NodeContext) bool
autoCreateMap func(nodeContext NodeContext) bool
visit func(nodeContext NodeContext) error
shouldVisitExtraFn func(nodeContext NodeContext) bool
shouldDeeplyTraverse func(nodeContext NodeContext) bool
visitedNodes []*NodeContext
pathParser PathParser
}
func (ns *NavigationStrategyImpl) GetPathParser() PathParser {
@@ -64,6 +66,10 @@ func (ns *NavigationStrategyImpl) AutoCreateMap(nodeContext NodeContext) bool {
return ns.autoCreateMap(nodeContext)
}
func (ns *NavigationStrategyImpl) ShouldDeeplyTraverse(nodeContext NodeContext) bool {
return ns.shouldDeeplyTraverse(nodeContext)
}
func (ns *NavigationStrategyImpl) ShouldTraverse(nodeContext NodeContext, nodeKey string) bool {
// we should traverse aliases (if enabled), but not visit them :/
if len(nodeContext.PathStack) == 0 {
@@ -84,7 +90,6 @@ func (ns *NavigationStrategyImpl) shouldVisit(nodeContext NodeContext) bool {
return true
}
log.Debug("tail len %v", len(nodeContext.Tail))
// SOMETHING HERE!
if ns.alreadyVisited(pathStack) || len(nodeContext.Tail) != 0 {
return false

View File

@@ -1,12 +1,13 @@
package yqlib
import (
"fmt"
"strconv"
"strings"
)
type PathParser interface {
ParsePath(path string) []string
ParsePath(path string) []interface{}
MatchesNextPathElement(nodeContext NodeContext, nodeKey string) bool
IsPathExpression(pathElement string) bool
}
@@ -42,9 +43,11 @@ func (p *pathParser) MatchesNextPathElement(nodeContext NodeContext, nodeKey str
if head == "**" || head == "*" {
return true
}
if strings.Contains(head, "==") {
var headString = fmt.Sprintf("%v", head)
if strings.Contains(headString, "==") {
log.Debug("ooh deep recursion time")
result := strings.SplitN(head, "==", 2)
result := strings.SplitN(headString, "==", 2)
path := strings.TrimSpace(result[0])
value := strings.TrimSpace(result[1])
log.Debug("path %v", path)
@@ -55,9 +58,9 @@ func (p *pathParser) MatchesNextPathElement(nodeContext NodeContext, nodeKey str
navigator := NewDataNavigator(navigationStrategy)
err := navigator.Traverse(nodeContext.Node, p.ParsePath(path))
if err != nil {
log.Error("Error deep recursing - ignoring")
log.Error(err.Error())
}
//crap handle error
log.Debug("done deep recursing, found %v matches", len(navigationStrategy.GetVisitedNodes()))
return len(navigationStrategy.GetVisitedNodes()) > 0
}
@@ -70,17 +73,18 @@ func (p *pathParser) MatchesNextPathElement(nodeContext NodeContext, nodeKey str
}
}
return matchesString(head, nodeKey)
return matchesString(headString, nodeKey)
}
func (p *pathParser) ParsePath(path string) []string {
func (p *pathParser) ParsePath(path string) []interface{} {
var paths = make([]interface{}, 0)
if path == "" {
return []string{}
return paths
}
return p.parsePathAccum([]string{}, path)
return p.parsePathAccum(paths, path)
}
func (p *pathParser) parsePathAccum(paths []string, remaining string) []string {
func (p *pathParser) parsePathAccum(paths []interface{}, remaining string) []interface{} {
head, tail := p.nextYamlPath(remaining)
if tail == "" {
return append(paths, head)
@@ -88,11 +92,16 @@ func (p *pathParser) parsePathAccum(paths []string, remaining string) []string {
return p.parsePathAccum(append(paths, head), tail)
}
func (p *pathParser) nextYamlPath(path string) (pathElement string, remaining string) {
func (p *pathParser) nextYamlPath(path string) (pathElement interface{}, remaining string) {
switch path[0] {
case '[':
// e.g [0].blah.cat -> we need to return "0" and "blah.cat"
return p.search(path[1:], []uint8{']'}, true)
var value, remainingBit = p.search(path[1:], []uint8{']'}, true)
var number, errParsingInt = strconv.ParseInt(value, 10, 64) // nolint
if errParsingInt == nil {
return number, remainingBit
}
return value, remainingBit
case '"':
// e.g "a.b".blah.cat -> we need to return "a.b" and "blah.cat"
return p.search(path[1:], []uint8{'"'}, true)

View File

@@ -10,20 +10,21 @@ var parser = NewPathParser()
var parsePathsTests = []struct {
path string
expectedPaths []string
expectedPaths []interface{}
}{
{"a.b", []string{"a", "b"}},
{"a.b.**", []string{"a", "b", "**"}},
{"a.b.*", []string{"a", "b", "*"}},
{"a.b[0]", []string{"a", "b", "0"}},
{"a.b.d[+]", []string{"a", "b", "d", "+"}},
{"a", []string{"a"}},
{"a.b.c", []string{"a", "b", "c"}},
{"\"a.b\".c", []string{"a.b", "c"}},
{"a.\"b.c\".d", []string{"a", "b.c", "d"}},
{"[1].a.d", []string{"1", "a", "d"}},
{"a[0].c", []string{"a", "0", "c"}},
{"[0]", []string{"0"}},
{"a.b", append(make([]interface{}, 0), "a", "b")},
{"a.b.**", append(make([]interface{}, 0), "a", "b", "**")},
{"a.b.*", append(make([]interface{}, 0), "a", "b", "*")},
{"a.b[0]", append(make([]interface{}, 0), "a", "b", int64(0))},
{"a.b.0", append(make([]interface{}, 0), "a", "b", "0")},
{"a.b.d[+]", append(make([]interface{}, 0), "a", "b", "d", "+")},
{"a", append(make([]interface{}, 0), "a")},
{"a.b.c", append(make([]interface{}, 0), "a", "b", "c")},
{"\"a.b\".c", append(make([]interface{}, 0), "a.b", "c")},
{"a.\"b.c\".d", append(make([]interface{}, 0), "a", "b.c", "d")},
{"[1].a.d", append(make([]interface{}, 0), int64(1), "a", "d")},
{"a[0].c", append(make([]interface{}, 0), "a", int64(0), "c")},
{"[0]", append(make([]interface{}, 0), int64(0))},
}
func TestPathParserParsePath(t *testing.T) {

View File

@@ -1,6 +1,6 @@
package yqlib
func ReadNavigationStrategy() NavigationStrategy {
func ReadNavigationStrategy(deeplyTraverseArrays bool) NavigationStrategy {
return &NavigationStrategyImpl{
visitedNodes: []*NodeContext{},
pathParser: NewPathParser(),
@@ -13,5 +13,18 @@ func ReadNavigationStrategy() NavigationStrategy {
visit: func(nodeContext NodeContext) error {
return nil
},
shouldDeeplyTraverse: func(nodeContext NodeContext) bool {
var isInArray = false
if len(nodeContext.PathStack) > 0 {
var lastElement = nodeContext.PathStack[len(nodeContext.PathStack)-1]
switch lastElement.(type) {
case int:
isInArray = true
default:
isInArray = false
}
}
return deeplyTraverseArrays || !isInArray
},
}
}

View File

@@ -10,6 +10,9 @@ func UpdateNavigationStrategy(updateCommand UpdateCommand, autoCreate bool) Navi
autoCreateMap: func(nodeContext NodeContext) bool {
return autoCreate
},
shouldDeeplyTraverse: func(nodeContext NodeContext) bool {
return true
},
visit: func(nodeContext NodeContext) error {
node := nodeContext.Node
changesToApply := updateCommand.Value

View File

@@ -1,8 +1,6 @@
package yqlib
import (
"strconv"
yaml "gopkg.in/yaml.v3"
)
@@ -18,30 +16,8 @@ func NewValueParser() ValueParser {
}
func (v *valueParser) Parse(argument string, customTag string) *yaml.Node {
var err interface{}
var tag = customTag
if tag == "" {
_, err = strconv.ParseBool(argument)
if err == nil {
tag = "!!bool"
}
_, err = strconv.ParseFloat(argument, 64)
if err == nil {
tag = "!!float"
}
_, err = strconv.ParseInt(argument, 10, 64)
if err == nil {
tag = "!!int"
}
if argument == "null" {
tag = "!!null"
}
if argument == "[]" {
return &yaml.Node{Tag: "!!seq", Kind: yaml.SequenceNode}
}
if argument == "[]" {
return &yaml.Node{Tag: "!!seq", Kind: yaml.SequenceNode}
}
log.Debugf("parsed value '%v', tag: '%v'", argument, tag)
return &yaml.Node{Value: argument, Tag: tag, Kind: yaml.ScalarNode}
return &yaml.Node{Value: argument, Tag: customTag, Kind: yaml.ScalarNode}
}

View File

@@ -13,13 +13,9 @@ var parseValueTests = []struct {
expectedTag string
testDescription string
}{
{"true", "", "!!bool", "boolean"},
{"true", "!!str", "!!str", "boolean forced as string"},
{"3.4", "", "!!float", "float"},
{"1212121", "", "!!int", "big number"},
{"1212121.1", "", "!!float", "big float number"},
{"3", "", "!!int", "int"},
{"null", "", "!!null", "null"},
{"3", "!!int", "!!int", "int"},
{"cat", "", "", "default"},
}
func TestValueParserParse(t *testing.T) {

View File

@@ -2,7 +2,6 @@
- increment version in snapcraft.yaml
- commit
- tag git with same version number
- be sure to also tag with 'v' for gopkg.in
- make sure local build passes
- push tag to git
- git push --tags

View File

@@ -1,4 +1,4 @@
#!/bin/sh
set -e
wget -O - -q https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s v1.21.0
wget -O- -nv https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s v1.23.1
go get golang.org/x/tools/cmd/goimports

View File

@@ -32,5 +32,5 @@ upload() {
done < <(find ./build -mindepth 1 -maxdepth 1 -print0)
}
# release
release
upload

View File

@@ -1,5 +1,5 @@
name: yq
version: '3.0.0-beta'
version: '3.1.2'
summary: A lightweight and portable command-line YAML processor
description: |
The aim of the project is to be the jq or sed of yaml files.

714
yq.go
View File

@@ -1,725 +1,17 @@
package main
import (
"bufio"
"fmt"
"io"
"io/ioutil"
"os"
"strconv"
"strings"
"github.com/mikefarah/yq/v3/pkg/yqlib"
errors "github.com/pkg/errors"
"github.com/spf13/cobra"
command "github.com/mikefarah/yq/v3/cmd"
logging "gopkg.in/op/go-logging.v1"
yaml "gopkg.in/yaml.v3"
)
var customTag = ""
var printMode = "v"
var writeInplace = false
var writeScript = ""
var outputToJSON = false
var overwriteFlag = false
var autoCreateFlag = true
var allowEmptyFlag = false
var appendFlag = false
var verbose = false
var version = false
var docIndex = "0"
var log = logging.MustGetLogger("yq")
var lib = yqlib.NewYqLib()
var valueParser = yqlib.NewValueParser()
func main() {
cmd := newCommandCLI()
cmd := command.New()
log := logging.MustGetLogger("yq")
if err := cmd.Execute(); err != nil {
log.Error(err.Error())
os.Exit(1)
}
}
func newCommandCLI() *cobra.Command {
var rootCmd = &cobra.Command{
Use: "yq",
Short: "yq is a lightweight and portable command-line YAML processor.",
Long: `yq is a lightweight and portable command-line YAML processor. It aims to be the jq or sed of yaml files.`,
RunE: func(cmd *cobra.Command, args []string) error {
if version {
cmd.Print(GetVersionDisplay())
return nil
}
cmd.Println(cmd.UsageString())
return nil
},
PersistentPreRun: func(cmd *cobra.Command, args []string) {
var format = logging.MustStringFormatter(
`%{color}%{time:15:04:05} %{shortfunc} [%{level:.4s}]%{color:reset} %{message}`,
)
var backend = logging.AddModuleLevel(
logging.NewBackendFormatter(logging.NewLogBackend(os.Stderr, "", 0), format))
if verbose {
backend.SetLevel(logging.DEBUG, "")
} else {
backend.SetLevel(logging.ERROR, "")
}
logging.SetBackend(backend)
},
}
rootCmd.PersistentFlags().BoolVarP(&verbose, "verbose", "v", false, "verbose mode")
rootCmd.PersistentFlags().BoolVarP(&outputToJSON, "tojson", "j", false, "output as json")
rootCmd.Flags().BoolVarP(&version, "version", "V", false, "Print version information and quit")
rootCmd.AddCommand(
createReadCmd(),
createWriteCmd(),
createPrefixCmd(),
createDeleteCmd(),
createNewCmd(),
createMergeCmd(),
)
rootCmd.SetOutput(os.Stdout)
return rootCmd
}
func createReadCmd() *cobra.Command {
var cmdRead = &cobra.Command{
Use: "read [yaml_file] [path_expression]",
Aliases: []string{"r"},
Short: "yq r [--doc/-d index] sample.yaml 'a.b.c'",
Example: `
yq read things.yaml 'a.b.c'
yq r - 'a.b.c' # reads from stdin
yq r things.yaml 'a.*.c'
yq r things.yaml 'a.**.c' # deep splat
yq r things.yaml 'a.(child.subchild==co*).c'
yq r -d1 things.yaml 'a.array[0].blah'
yq r things.yaml 'a.array[*].blah'
yq r -- things.yaml '--key-starting-with-dashes.blah'
`,
Long: "Outputs the value of the given path in the yaml file to STDOUT",
RunE: readProperty,
}
cmdRead.PersistentFlags().StringVarP(&docIndex, "doc", "d", "0", "process document index number (0 based, * for all documents)")
cmdRead.PersistentFlags().StringVarP(&printMode, "printMode", "p", "v", "print mode (v (values, default), p (paths), pv (path and value pairs)")
return cmdRead
}
func createWriteCmd() *cobra.Command {
var cmdWrite = &cobra.Command{
Use: "write [yaml_file] [path_expression] [value]",
Aliases: []string{"w"},
Short: "yq w [--inplace/-i] [--script/-s script_file] [--doc/-d index] sample.yaml 'a.b.c' newValue",
Example: `
yq write things.yaml 'a.b.c' true
yq write things.yaml 'a.*.c' true
yq write things.yaml 'a.**' true
yq write things.yaml 'a.(child.subchild==co*).c' true
yq write things.yaml 'a.b.c' --tag '!!str' true # force 'true' to be interpreted as a string instead of bool
yq write things.yaml 'a.b.c' --tag '!!float' 3
yq write --inplace -- things.yaml 'a.b.c' '--cat' # need to use '--' to stop processing arguments as flags
yq w -i things.yaml 'a.b.c' cat
yq w --script update_script.yaml things.yaml
yq w -i -s update_script.yaml things.yaml
yq w things.yaml 'a.b.d[+]' foo # appends a new node to the 'd' array
yq w --doc 2 things.yaml 'a.b.d[+]' foo # updates the 3rd document of the yaml file
`,
Long: `Updates the matching nodes of path expression to the specified value
Outputs to STDOUT unless the inplace flag is used, in which case the file is updated instead.
Append value to array adds the value to the end of array.
Update Scripts:
Note that you can give an update script to perform more sophisticated update. Update script
format is list of update commands (update or delete) like so:
---
- command: update
path: b.c
value:
#great
things: frog # wow!
- command: delete
path: b.d
`,
RunE: writeProperty,
}
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(&customTag, "tag", "t", "", "set yaml tag (e.g. !!int)")
cmdWrite.PersistentFlags().StringVarP(&docIndex, "doc", "d", "0", "process document index number (0 based, * for all documents)")
return cmdWrite
}
func createPrefixCmd() *cobra.Command {
var cmdPrefix = &cobra.Command{
Use: "prefix [yaml_file] [path]",
Aliases: []string{"p"},
Short: "yq p [--inplace/-i] [--doc/-d index] sample.yaml a.b.c",
Example: `
yq prefix things.yaml 'a.b.c'
yq prefix --inplace things.yaml 'a.b.c'
yq prefix --inplace -- things.yaml '--key-starting-with-dash' # need to use '--' to stop processing arguments as flags
yq p -i things.yaml 'a.b.c'
yq p --doc 2 things.yaml 'a.b.d'
yq p -d2 things.yaml 'a.b.d'
`,
Long: `Prefixes w.r.t to the yaml file at the given path.
Outputs to STDOUT unless the inplace flag is used, in which case the file is updated instead.
`,
RunE: prefixProperty,
}
cmdPrefix.PersistentFlags().BoolVarP(&writeInplace, "inplace", "i", false, "update the yaml file inplace")
cmdPrefix.PersistentFlags().StringVarP(&docIndex, "doc", "d", "0", "process document index number (0 based, * for all documents)")
return cmdPrefix
}
func createDeleteCmd() *cobra.Command {
var cmdDelete = &cobra.Command{
Use: "delete [yaml_file] [path_expression]",
Aliases: []string{"d"},
Short: "yq d [--inplace/-i] [--doc/-d index] sample.yaml a.b.c",
Example: `
yq delete things.yaml 'a.b.c'
yq delete things.yaml 'a.*.c'
yq delete things.yaml 'a.(child.subchild==co*).c'
yq delete things.yaml 'a.**'
yq delete --inplace things.yaml 'a.b.c'
yq delete --inplace -- things.yaml '--key-starting-with-dash' # need to use '--' to stop processing arguments as flags
yq d -i things.yaml 'a.b.c'
`,
Long: `Deletes the nodes matching the given path expression from the YAML file.
Outputs to STDOUT unless the inplace flag is used, in which case the file is updated instead.
`,
RunE: deleteProperty,
}
cmdDelete.PersistentFlags().BoolVarP(&writeInplace, "inplace", "i", false, "update the yaml file inplace")
cmdDelete.PersistentFlags().StringVarP(&docIndex, "doc", "d", "0", "process document index number (0 based, * for all documents)")
return cmdDelete
}
func createNewCmd() *cobra.Command {
var cmdNew = &cobra.Command{
Use: "new [path] [value]",
Aliases: []string{"n"},
Short: "yq n [--script/-s script_file] a.b.c newValue",
Example: `
yq new 'a.b.c' cat
yq n 'a.b.c' --tag '!!str' true # force 'true' to be interpreted as a string instead of bool
yq n 'a.b[+]' cat
yq n -- '--key-starting-with-dash' cat # need to use '--' to stop processing arguments as flags
yq n --script create_script.yaml
`,
Long: `Creates a new yaml w.r.t the given path and value.
Outputs to STDOUT
Create Scripts:
Note that you can give a create script to perform more sophisticated yaml. This follows the same format as the update script.
`,
RunE: newProperty,
}
cmdNew.PersistentFlags().StringVarP(&writeScript, "script", "s", "", "yaml script for creating yaml")
cmdNew.PersistentFlags().StringVarP(&customTag, "tag", "t", "", "set yaml tag (e.g. !!int)")
return cmdNew
}
func createMergeCmd() *cobra.Command {
var cmdMerge = &cobra.Command{
Use: "merge [initial_yaml_file] [additional_yaml_file]...",
Aliases: []string{"m"},
Short: "yq m [--inplace/-i] [--doc/-d index] [--overwrite/-x] [--append/-a] sample.yaml sample2.yaml",
Example: `
yq merge things.yaml other.yaml
yq merge --inplace things.yaml other.yaml
yq m -i things.yaml other.yaml
yq m --overwrite things.yaml other.yaml
yq m -i -x things.yaml other.yaml
yq m -i -a things.yaml other.yaml
yq m -i --autocreate=false things.yaml other.yaml
`,
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.
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.
`,
RunE: mergeProperties,
}
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(&autoCreateFlag, "autocreate", "c", true, "automatically create any missing entries")
cmdMerge.PersistentFlags().BoolVarP(&appendFlag, "append", "a", false, "update the yaml file by appending array values")
cmdMerge.PersistentFlags().BoolVarP(&allowEmptyFlag, "allow-empty", "e", false, "allow empty yaml files")
cmdMerge.PersistentFlags().StringVarP(&docIndex, "doc", "d", "0", "process document index number (0 based, * for all documents)")
return cmdMerge
}
func readProperty(cmd *cobra.Command, args []string) error {
var path = ""
if len(args) < 1 {
return errors.New("Must provide filename")
} else if len(args) > 1 {
path = args[1]
}
var updateAll, docIndexInt, errorParsingDocIndex = parseDocumentIndex()
if errorParsingDocIndex != nil {
return errorParsingDocIndex
}
matchingNodes, errorReadingStream := readYamlFile(args[0], path, updateAll, docIndexInt)
if errorReadingStream != nil {
return errorReadingStream
}
return printResults(matchingNodes, cmd)
}
func readYamlFile(filename string, path string, updateAll bool, docIndexInt int) ([]*yqlib.NodeContext, error) {
var matchingNodes []*yqlib.NodeContext
var currentIndex = 0
var errorReadingStream = readStream(filename, func(decoder *yaml.Decoder) error {
for {
var dataBucket yaml.Node
errorReading := decoder.Decode(&dataBucket)
if errorReading == io.EOF {
return handleEOF(updateAll, docIndexInt, currentIndex)
}
var errorParsing error
matchingNodes, errorParsing = appendDocument(matchingNodes, dataBucket, path, updateAll, docIndexInt, currentIndex)
if errorParsing != nil {
return errorParsing
}
currentIndex = currentIndex + 1
}
})
return matchingNodes, errorReadingStream
}
func handleEOF(updateAll bool, docIndexInt int, currentIndex int) error {
log.Debugf("done %v / %v", currentIndex, docIndexInt)
if !updateAll && currentIndex <= docIndexInt {
return fmt.Errorf("Could not process document index %v as there are only %v document(s)", docIndex, currentIndex)
}
return nil
}
func appendDocument(originalMatchingNodes []*yqlib.NodeContext, dataBucket yaml.Node, path string, updateAll bool, docIndexInt int, currentIndex int) ([]*yqlib.NodeContext, error) {
log.Debugf("processing document %v - requested index %v", currentIndex, docIndexInt)
yqlib.DebugNode(&dataBucket)
if !updateAll && currentIndex != docIndexInt {
return originalMatchingNodes, nil
}
log.Debugf("reading %v in document %v", path, currentIndex)
matchingNodes, errorParsing := lib.Get(&dataBucket, path)
if errorParsing != nil {
return nil, errors.Wrapf(errorParsing, "Error reading path in document index %v", currentIndex)
}
return append(originalMatchingNodes, matchingNodes...), nil
}
func printValue(node *yaml.Node, cmd *cobra.Command) error {
if node.Kind == yaml.ScalarNode {
cmd.Print(node.Value)
return nil
}
bufferedWriter := bufio.NewWriter(cmd.OutOrStdout())
defer safelyFlush(bufferedWriter)
var encoder yqlib.Encoder
if outputToJSON {
encoder = yqlib.NewJsonEncoder(bufferedWriter)
} else {
encoder = yqlib.NewYamlEncoder(bufferedWriter)
}
if err := encoder.Encode(node); err != nil {
return err
}
return nil
}
func printResults(matchingNodes []*yqlib.NodeContext, cmd *cobra.Command) error {
if len(matchingNodes) == 0 {
log.Debug("no matching results, nothing to print")
return nil
}
for index, mappedDoc := range matchingNodes {
switch printMode {
case "p":
cmd.Print(lib.PathStackToString(mappedDoc.PathStack))
if index < len(matchingNodes)-1 {
cmd.Print("\n")
}
case "pv", "vp":
// put it into a node and print that.
var parentNode = yaml.Node{Kind: yaml.MappingNode}
parentNode.Content = make([]*yaml.Node, 2)
parentNode.Content[0] = &yaml.Node{Kind: yaml.ScalarNode, Value: lib.PathStackToString(mappedDoc.PathStack)}
parentNode.Content[1] = mappedDoc.Node
if err := printValue(&parentNode, cmd); err != nil {
return err
}
default:
if err := printValue(mappedDoc.Node, cmd); err != nil {
return err
}
// Printing our Scalars does not print a new line at the end
// we only want to do that if there are more values (so users can easily script extraction of values in the yaml)
if index < len(matchingNodes)-1 && mappedDoc.Node.Kind == yaml.ScalarNode {
cmd.Print("\n")
}
}
}
return 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 *yaml.Node, currentIndex int) error
func mapYamlDecoder(updateData updateDataFn, encoder yqlib.Encoder) yamlDecoderFn {
return func(decoder *yaml.Decoder) error {
var dataBucket yaml.Node
var errorReading error
var errorWriting error
var errorUpdating error
var currentIndex = 0
var updateAll, docIndexInt, errorParsingDocIndex = parseDocumentIndex()
if errorParsingDocIndex != nil {
return errorParsingDocIndex
}
for {
log.Debugf("Read doc %v", currentIndex)
errorReading = decoder.Decode(&dataBucket)
if errorReading == io.EOF {
if !updateAll && currentIndex <= docIndexInt {
return fmt.Errorf("asked to process document index %v but there are only %v document(s)", docIndex, currentIndex)
}
return nil
} else if errorReading != nil {
return errors.Wrapf(errorReading, "Error reading document at index %v, %v", currentIndex, errorReading)
}
errorUpdating = updateData(&dataBucket, currentIndex)
if errorUpdating != nil {
return errors.Wrapf(errorUpdating, "Error updating document at index %v", currentIndex)
}
errorWriting = encoder.Encode(&dataBucket)
if errorWriting != nil {
return errors.Wrapf(errorWriting, "Error writing document at index %v, %v", currentIndex, errorWriting)
}
currentIndex = currentIndex + 1
}
}
}
func writeProperty(cmd *cobra.Command, args []string) error {
var updateCommands, updateCommandsError = readUpdateCommands(args, 3, "Must provide <filename> <path_to_update> <value>")
if updateCommandsError != nil {
return updateCommandsError
}
return updateDoc(args[0], updateCommands, cmd.OutOrStdout())
}
func mergeProperties(cmd *cobra.Command, args []string) error {
if len(args) < 2 {
return errors.New("Must provide at least 2 yaml files")
}
// first generate update commands from the file
var filesToMerge = args[1:]
var updateCommands []yqlib.UpdateCommand = make([]yqlib.UpdateCommand, 0)
for _, fileToMerge := range filesToMerge {
matchingNodes, errorProcessingFile := readYamlFile(fileToMerge, "**", false, 0)
if errorProcessingFile != nil && (!allowEmptyFlag || !strings.HasPrefix(errorProcessingFile.Error(), "Could not process document index")) {
return errorProcessingFile
}
for _, matchingNode := range matchingNodes {
mergePath := lib.MergePathStackToString(matchingNode.PathStack, appendFlag)
updateCommands = append(updateCommands, yqlib.UpdateCommand{Command: "update", Path: mergePath, Value: matchingNode.Node, Overwrite: overwriteFlag})
}
}
return updateDoc(args[0], updateCommands, cmd.OutOrStdout())
}
func newProperty(cmd *cobra.Command, args []string) error {
var updateCommands, updateCommandsError = readUpdateCommands(args, 2, "Must provide <path_to_update> <value>")
if updateCommandsError != nil {
return updateCommandsError
}
newNode := lib.New(updateCommands[0].Path)
for _, updateCommand := range updateCommands {
errorUpdating := lib.Update(&newNode, updateCommand, true)
if errorUpdating != nil {
return errorUpdating
}
}
var encoder = yaml.NewEncoder(cmd.OutOrStdout())
encoder.SetIndent(2)
errorEncoding := encoder.Encode(&newNode)
encoder.Close()
return errorEncoding
}
func prefixProperty(cmd *cobra.Command, args []string) error {
if len(args) < 2 {
return errors.New("Must provide <filename> <prefixed_path>")
}
updateCommand := yqlib.UpdateCommand{Command: "update", Path: args[1]}
log.Debugf("args %v", args)
var updateAll, docIndexInt, errorParsingDocIndex = parseDocumentIndex()
if errorParsingDocIndex != nil {
return errorParsingDocIndex
}
var updateData = func(dataBucket *yaml.Node, currentIndex int) error {
return prefixDocument(updateAll, docIndexInt, currentIndex, dataBucket, updateCommand)
}
return readAndUpdate(cmd.OutOrStdout(), args[0], updateData)
}
func prefixDocument(updateAll bool, docIndexInt int, currentIndex int, dataBucket *yaml.Node, updateCommand yqlib.UpdateCommand) error {
if updateAll || currentIndex == docIndexInt {
log.Debugf("Prefixing document %v", currentIndex)
yqlib.DebugNode(dataBucket)
updateCommand.Value = dataBucket.Content[0]
dataBucket.Content = make([]*yaml.Node, 1)
newNode := lib.New(updateCommand.Path)
dataBucket.Content[0] = &newNode
errorUpdating := lib.Update(dataBucket, updateCommand, true)
if errorUpdating != nil {
return errorUpdating
}
}
return nil
}
func deleteProperty(cmd *cobra.Command, args []string) error {
if len(args) < 2 {
return errors.New("Must provide <filename> <path_to_delete>")
}
var updateCommands []yqlib.UpdateCommand = make([]yqlib.UpdateCommand, 1)
updateCommands[0] = yqlib.UpdateCommand{Command: "delete", Path: args[1]}
return updateDoc(args[0], updateCommands, cmd.OutOrStdout())
}
func updateDoc(inputFile string, updateCommands []yqlib.UpdateCommand, writer io.Writer) error {
var updateAll, docIndexInt, errorParsingDocIndex = parseDocumentIndex()
if errorParsingDocIndex != nil {
return errorParsingDocIndex
}
var updateData = func(dataBucket *yaml.Node, currentIndex int) error {
if updateAll || currentIndex == docIndexInt {
log.Debugf("Updating doc %v", currentIndex)
for _, updateCommand := range updateCommands {
log.Debugf("Processing update to Path %v", updateCommand.Path)
errorUpdating := lib.Update(dataBucket, updateCommand, autoCreateFlag)
if errorUpdating != nil {
return errorUpdating
}
}
}
return nil
}
return readAndUpdate(writer, inputFile, updateData)
}
func readAndUpdate(stdOut io.Writer, inputFile string, updateData updateDataFn) error {
var destination io.Writer
var destinationName string
if writeInplace {
info, err := os.Stat(inputFile)
if err != nil {
return err
}
tempFile, err := ioutil.TempFile("", "temp")
if err != nil {
return err
}
destinationName = tempFile.Name()
err = os.Chmod(destinationName, info.Mode())
if err != nil {
return err
}
destination = tempFile
defer func() {
safelyCloseFile(tempFile)
safelyRenameFile(tempFile.Name(), inputFile)
}()
} else {
destination = stdOut
destinationName = "Stdout"
}
log.Debugf("Writing to %v from %v", destinationName, inputFile)
bufferedWriter := bufio.NewWriter(destination)
defer safelyFlush(bufferedWriter)
var encoder yqlib.Encoder
if outputToJSON {
encoder = yqlib.NewJsonEncoder(bufferedWriter)
} else {
encoder = yqlib.NewYamlEncoder(bufferedWriter)
}
return readStream(inputFile, mapYamlDecoder(updateData, encoder))
}
type updateCommandParsed struct {
Command string
Path string
Value yaml.Node
}
func readUpdateCommands(args []string, expectedArgs int, badArgsMessage string) ([]yqlib.UpdateCommand, error) {
var updateCommands []yqlib.UpdateCommand = make([]yqlib.UpdateCommand, 0)
if writeScript != "" {
var parsedCommands = make([]updateCommandParsed, 0)
err := readData(writeScript, 0, &parsedCommands)
if err != nil && err != io.EOF {
return nil, err
}
log.Debugf("Read write commands file '%v'", parsedCommands)
for index := range parsedCommands {
parsedCommand := parsedCommands[index]
updateCommand := yqlib.UpdateCommand{Command: parsedCommand.Command, Path: parsedCommand.Path, Value: &parsedCommand.Value, Overwrite: true}
updateCommands = append(updateCommands, updateCommand)
}
log.Debugf("Read write commands file '%v'", updateCommands)
} else if len(args) < expectedArgs {
return nil, errors.New(badArgsMessage)
} else {
updateCommands = make([]yqlib.UpdateCommand, 1)
log.Debug("args %v", args)
log.Debug("path %v", args[expectedArgs-2])
log.Debug("Value %v", args[expectedArgs-1])
updateCommands[0] = yqlib.UpdateCommand{Command: "update", Path: args[expectedArgs-2], Value: valueParser.Parse(args[expectedArgs-1], customTag), Overwrite: true}
}
return updateCommands, nil
}
func safelyRenameFile(from string, to string) {
if renameError := os.Rename(from, to); renameError != nil {
log.Debugf("Error renaming from %v to %v, attempting to copy contents", from, to)
log.Debug(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.Error(copyError.Error())
} else {
removeErr := os.Remove(from)
if removeErr != nil {
log.Errorf("failed removing original file: %s", from)
}
}
}
}
// 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) // nolint gosec
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) {
if err := writer.Flush(); err != nil {
log.Error("Error flushing writer!")
log.Error(err.Error())
}
}
func safelyCloseFile(file *os.File) {
err := file.Close()
if err != nil {
log.Error("Error closing file!")
log.Error(err.Error())
}
}
type yamlDecoderFn func(*yaml.Decoder) error
func readStream(filename string, yamlDecoder yamlDecoderFn) error {
if filename == "" {
return errors.New("Must provide filename")
}
var stream io.Reader
if filename == "-" {
stream = bufio.NewReader(os.Stdin)
} else {
file, err := os.Open(filename) // nolint gosec
if err != nil {
return err
}
defer safelyCloseFile(file)
stream = file
}
return yamlDecoder(yaml.NewDecoder(stream))
}
func readData(filename string, indexToRead int, parsedData interface{}) error {
return readStream(filename, func(decoder *yaml.Decoder) error {
for currentIndex := 0; currentIndex < indexToRead; currentIndex++ {
errorSkipping := decoder.Decode(parsedData)
if errorSkipping != nil {
return errors.Wrapf(errorSkipping, "Error processing document at index %v, %v", currentIndex, errorSkipping)
}
}
return decoder.Decode(parsedData)
})
}