├── README.md ├── go.mod └── main.go /README.md: -------------------------------------------------------------------------------- 1 | # jsonargs 2 | 3 | xargs for JSON stream 4 | 5 | ## Usage 6 | 7 | ### input data 8 | 9 | ``` 10 | { "name": "foo1", "value": "bar1" } 11 | { "name": "foo2", "value": "bar2" } 12 | { "name": "foo3", "value": "bar3" } 13 | { "name": "foo4", "value": "bar4" } 14 | { "name": "foo5", "value": "bar5" } 15 | ``` 16 | 17 | ### sequencial execute 18 | 19 | ``` 20 | $ cat input.dat | jsonargs echo '{{.name}}' '{{.value}}' 21 | foo1 bar1 22 | foo2 bar2 23 | foo3 bar3 24 | foo4 bar4 25 | foo5 bar5 26 | ``` 27 | 28 | ### handle array 29 | 30 | If you want to handle input data as array, please specify `-a` flag. 31 | 32 | ``` 33 | [ 34 | { "name": "foo1", "value": "bar1" }, 35 | { "name": "foo2", "value": "bar2" }, 36 | { "name": "foo3", "value": "bar3" }, 37 | { "name": "foo4", "value": "bar4" }, 38 | { "name": "foo5", "value": "bar5" } 39 | ] 40 | ``` 41 | 42 | ``` 43 | $ cat input.dat | jsonargs -a echo '{{.name}}' '{{.value}}' 44 | foo1 bar1 45 | foo2 bar2 46 | foo3 bar3 47 | foo4 bar4 48 | foo5 bar5 49 | ``` 50 | 51 | ## Installation 52 | 53 | ``` 54 | go get github.com/mattn/jsonargs 55 | ``` 56 | 57 | ## License 58 | 59 | MIT 60 | 61 | ## Author 62 | 63 | Yasuhiro Matsumoto (a.k.a. mattn) 64 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/mattn/jsonargs 2 | 3 | go 1.14 4 | -------------------------------------------------------------------------------- /main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "bufio" 5 | "bytes" 6 | "encoding/json" 7 | "flag" 8 | "fmt" 9 | "log" 10 | "os" 11 | "os/exec" 12 | "strings" 13 | "text/template" 14 | ) 15 | 16 | var ( 17 | failOnError = flag.Bool("f", false, "fail on error") 18 | parallel = flag.Bool("p", false, "parallel") 19 | array = flag.Bool("a", false, "input array") 20 | wait = flag.Bool("P", false, "parallel ant wait all") 21 | ) 22 | 23 | func main() { 24 | flag.Parse() 25 | 26 | args := flag.Args() 27 | if len(args) == 0 { 28 | flag.Usage() 29 | os.Exit(2) 30 | } 31 | 32 | if *wait { 33 | *parallel = true 34 | } 35 | 36 | funcs := template.FuncMap{ 37 | "trim": func(s string) string { 38 | return strings.TrimSpace(s) 39 | }, 40 | "replace": func(s1, s2, s string) string { 41 | return strings.Replace(s, s1, s2, -1) 42 | }, 43 | } 44 | 45 | targs := make([]*template.Template, len(args)) 46 | for i, arg := range args { 47 | t, err := template.New(fmt.Sprintf("arg%d", i)).Funcs(funcs).Parse(arg) 48 | if err != nil { 49 | log.Fatal(err) 50 | } 51 | targs[i] = t 52 | } 53 | var cmds []*exec.Cmd 54 | 55 | if *array { 56 | var vv []interface{} 57 | err := json.NewDecoder(os.Stdin).Decode(&vv) 58 | if err != nil { 59 | log.Fatal(err) 60 | } 61 | for _, v := range vv { 62 | xargs := make([]string, len(targs)) 63 | for i, t := range targs { 64 | var buf bytes.Buffer 65 | err = t.Execute(&buf, v) 66 | if err != nil { 67 | log.Fatal(err) 68 | } 69 | xargs[i] = buf.String() 70 | } 71 | cmd := exec.Command(xargs[0], xargs[1:]...) 72 | cmd.Stdout = os.Stdout 73 | cmd.Stderr = os.Stderr 74 | if *parallel { 75 | err = cmd.Start() 76 | if *wait { 77 | cmds = append(cmds, cmd) 78 | } 79 | } else { 80 | err = cmd.Run() 81 | } 82 | if *failOnError && err != nil { 83 | log.Fatal(err) 84 | } 85 | } 86 | if *parallel && *wait { 87 | for _, cmd := range cmds { 88 | cmd.Wait() 89 | } 90 | } 91 | return 92 | } 93 | 94 | scan := bufio.NewScanner(os.Stdin) 95 | 96 | for scan.Scan() { 97 | var v interface{} 98 | err := json.Unmarshal(scan.Bytes(), &v) 99 | if err != nil { 100 | if *failOnError { 101 | log.Fatal(err) 102 | } 103 | continue 104 | } 105 | xargs := make([]string, len(targs)) 106 | for i, t := range targs { 107 | var buf bytes.Buffer 108 | err = t.Execute(&buf, v) 109 | if err != nil { 110 | log.Fatal(err) 111 | } 112 | xargs[i] = buf.String() 113 | } 114 | cmd := exec.Command(xargs[0], xargs[1:]...) 115 | cmd.Stdout = os.Stdout 116 | cmd.Stderr = os.Stderr 117 | if *parallel { 118 | err = cmd.Start() 119 | if *wait { 120 | cmds = append(cmds, cmd) 121 | } 122 | } else { 123 | err = cmd.Run() 124 | } 125 | if *failOnError && err != nil { 126 | log.Fatal(err) 127 | } 128 | } 129 | 130 | if *parallel && *wait { 131 | for _, cmd := range cmds { 132 | cmd.Wait() 133 | } 134 | } 135 | if err := scan.Err(); err != nil { 136 | log.Fatal(err) 137 | } 138 | } 139 | --------------------------------------------------------------------------------