diff --git a/examples/multiple_docs.yaml b/examples/multiple_docs.yaml new file mode 100644 index 00000000..a65d33ab --- /dev/null +++ b/examples/multiple_docs.yaml @@ -0,0 +1,15 @@ +a: Easy! as one two three +b: + c: 2 + d: [3, 4] + e: + - name: fred + value: 3 + - name: sam + value: 4 +--- +another: + document: here +--- +wow: + - here is another \ No newline at end of file diff --git a/examples/sample.yaml b/examples/sample.yaml index 2024cbf4..b26830e8 100644 --- a/examples/sample.yaml +++ b/examples/sample.yaml @@ -6,4 +6,4 @@ b: - name: fred value: 3 - name: sam - value: 4 + value: 4 \ No newline at end of file diff --git a/vendor/vendor.json b/vendor/vendor.json index f7ca787a..92fd549a 100644 --- a/vendor/vendor.json +++ b/vendor/vendor.json @@ -33,10 +33,10 @@ "revisionTime": "2017-08-24T17:57:12Z" }, { - "checksumSHA1": "RDJpJQwkF012L6m/2BJizyOksNw=", + "checksumSHA1": "ZSWoOPUNRr5+3dhkLK3C4cZAQPk=", "path": "gopkg.in/yaml.v2", - "revision": "eb3733d160e74a9c7e442f435eb3bea458e1d19f", - "revisionTime": "2017-08-12T16:00:11Z" + "revision": "5420a8b6744d3b0345ab293f6fcba19c978f1183", + "revisionTime": "2018-03-28T19:50:20Z" } ], "rootPath": "github.com/mikefarah/yq" diff --git a/yq.go b/yq.go index 6538fb25..88cb4917 100644 --- a/yq.go +++ b/yq.go @@ -1,8 +1,10 @@ package main import ( + "bufio" "errors" "fmt" + "io" "io/ioutil" "os" "strconv" @@ -20,6 +22,7 @@ var outputToJSON = false var overwriteFlag = false var verbose = false var version = false +var docIndex = 0 var log = logging.MustGetLogger("yq") func main() { @@ -77,10 +80,10 @@ func newCommandCLI() *cobra.Command { } func createReadCmd() *cobra.Command { - return &cobra.Command{ + var cmdRead = &cobra.Command{ Use: "read [yaml_file] [path]", Aliases: []string{"r"}, - Short: "yq r sample.yaml a.b.c", + Short: "yq r [--doc/-d document_index] sample.yaml a.b.c", Example: ` yq read things.yaml a.b.c yq r - a.b.c (reads from stdin) @@ -91,6 +94,8 @@ yq r things.yaml a.array[*].blah Long: "Outputs the value of the given path in the yaml file to STDOUT", RunE: readProperty, } + cmdRead.PersistentFlags().IntVarP(&docIndex, "doc", "d", 0, "process document index number (0 based)") + return cmdRead } func createWriteCmd() *cobra.Command { @@ -499,22 +504,39 @@ func marshalContext(context interface{}) (string, error) { return outStr, nil } +func safelyCloseFile(file *os.File) { + err := file.Close() + if err != nil { + fmt.Println("Error closing file!") + fmt.Println(err.Error()) + } +} + func readData(filename string, parsedData interface{}) error { if filename == "" { return errors.New("Must provide filename") } - var rawData []byte - var err error + var stream io.Reader if filename == "-" { - rawData, err = ioutil.ReadAll(os.Stdin) + stream = bufio.NewReader(os.Stdin) } else { - rawData, err = ioutil.ReadFile(filename) + file, err := os.Open(filename) + if err != nil { + return err + } + defer safelyCloseFile(file) + stream = file } - if err != nil { - return err + var decoder = yaml.NewDecoder(stream) + // naive implementation of document indexing, decodes all the yaml documents + // before the docIndex and throws them away. + for currentIndex := 0; currentIndex < docIndex; currentIndex++ { + errorSkipping := decoder.Decode(parsedData) + if errorSkipping != nil { + return fmt.Errorf("Error processing document at index %v, %v", currentIndex, errorSkipping) + } } - - return yaml.Unmarshal(rawData, parsedData) + return decoder.Decode(parsedData) } diff --git a/yq_test.go b/yq_test.go index 9df68df3..5eda4fc1 100644 --- a/yq_test.go +++ b/yq_test.go @@ -28,6 +28,13 @@ func TestRead(t *testing.T) { assertResult(t, 2, result) } +func TestReadMulti(t *testing.T) { + docIndex = 1 + result, _ := read([]string{"examples/multiple_docs.yaml", "another.document"}) + assertResult(t, "here", result) + docIndex = 0 +} + func TestReadArray(t *testing.T) { result, _ := read([]string{"examples/sample_array.yaml", "[1]"}) assertResult(t, 2, result)