mirror of
https://github.com/acaloiaro/struct
synced 2026-07-21 18:29:17 +00:00
Initial commit
This commit is contained in:
commit
317e69024b
3 changed files with 170 additions and 0 deletions
22
README.md
Normal file
22
README.md
Normal file
|
|
@ -0,0 +1,22 @@
|
||||||
|
# struct
|
||||||
|
|
||||||
|
A simple unix utility for structuring string data on the command line.
|
||||||
|
|
||||||
|
# example usage
|
||||||
|
|
||||||
|
## string output
|
||||||
|
```
|
||||||
|
$ ls -l | struct -fields permissions,count,user,group,,,,,file_name -output string
|
||||||
|
permissions:-rw-r--r-- count:1 user:adriano group:staff 84 Sep 23 22:55 file_name:README.md
|
||||||
|
permissions:-rw------- count:1 user:adriano group:staff 39 Sep 23 21:08 file_name:go.mod
|
||||||
|
permissions:-rw-r--r-- count:1 user:adriano group:staff 2531 Sep 23 22:54 file_name:struct.go
|
||||||
|
```
|
||||||
|
|
||||||
|
## json output
|
||||||
|
|
||||||
|
```bash
|
||||||
|
$ ls -l | struct -fields permissions,count,user,group,,,,,file_name -output json
|
||||||
|
{"count":"1","file_name":"README.md","group":"staff","permissions":"-rw-r--r--","user":"adriano"}
|
||||||
|
{"count":"1","file_name":"go.mod","group":"staff","permissions":"-rw-------","user":"adriano"}
|
||||||
|
{"count":"1","file_name":"struct.go","group":"staff","permissions":"-rw-r--r--","user":"adriano"}
|
||||||
|
```
|
||||||
3
go.mod
Normal file
3
go.mod
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
module adriano.fyi/pkg/struct
|
||||||
|
|
||||||
|
go 1.12
|
||||||
145
struct.go
Normal file
145
struct.go
Normal file
|
|
@ -0,0 +1,145 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bufio"
|
||||||
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
|
"flag"
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
type fields []string
|
||||||
|
|
||||||
|
var fieldsFlag fields
|
||||||
|
var sepFlag string
|
||||||
|
var outFlag string
|
||||||
|
|
||||||
|
var in string
|
||||||
|
var fieldsProvided int
|
||||||
|
|
||||||
|
func (f *fields) String() string {
|
||||||
|
return fmt.Sprint(*f)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *fields) Set(value string) error {
|
||||||
|
if len(*f) > 0 {
|
||||||
|
return errors.New("fields switch already set")
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, field := range strings.Split(value, ",") {
|
||||||
|
*f = append(*f, field)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
defaultFieldSeparator = " "
|
||||||
|
defaultOutput = "string"
|
||||||
|
fieldsUsage = "comma-separated list of fields corresponding to the input data's fields\n\n" +
|
||||||
|
"Example\n\n" +
|
||||||
|
"$ echo \"foo1 bar1\" | struct -fields foo,bar\n" +
|
||||||
|
"$ foo:foo1 bar:bar1\n"
|
||||||
|
outputUsage = "the desired output format: json or string"
|
||||||
|
separatorUsage = "the character that separates fields in the input data"
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
|
||||||
|
flag.Var(&fieldsFlag, "fields", fieldsUsage)
|
||||||
|
flag.StringVar(&sepFlag, "separator", defaultFieldSeparator, separatorUsage)
|
||||||
|
flag.StringVar(&outFlag, "output", defaultOutput, outputUsage)
|
||||||
|
setupFlags(flag.CommandLine)
|
||||||
|
|
||||||
|
flag.Parse()
|
||||||
|
}
|
||||||
|
|
||||||
|
func setupFlags(f *flag.FlagSet) {
|
||||||
|
f.Usage = func() {
|
||||||
|
fmt.Println("\nCreate structured data input strings")
|
||||||
|
|
||||||
|
f.PrintDefaults()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var sb strings.Builder
|
||||||
|
var jsonMap = make(map[string]string)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
fieldsProvided = len(fieldsFlag)
|
||||||
|
|
||||||
|
scanner := bufio.NewScanner(os.Stdin)
|
||||||
|
|
||||||
|
var i int
|
||||||
|
var field, v string
|
||||||
|
|
||||||
|
for scanner.Scan() {
|
||||||
|
in = scanner.Text()
|
||||||
|
|
||||||
|
inputFields := strings.Fields(in)
|
||||||
|
|
||||||
|
for i, v = range inputFields {
|
||||||
|
if i < fieldsProvided {
|
||||||
|
|
||||||
|
field = fieldsFlag[i]
|
||||||
|
} else {
|
||||||
|
field = ""
|
||||||
|
}
|
||||||
|
|
||||||
|
buildOutput(field, v)
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Println(out())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func out() (out string) {
|
||||||
|
if outFlag == "string" {
|
||||||
|
out = sb.String()
|
||||||
|
sb.Reset()
|
||||||
|
} else if outFlag == "json" {
|
||||||
|
o, _ := json.Marshal(jsonMap)
|
||||||
|
out = string(o)
|
||||||
|
for k := range jsonMap {
|
||||||
|
delete(jsonMap, k)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
out = ""
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func buildOutput(field, value string) error {
|
||||||
|
if outFlag == "string" {
|
||||||
|
buildString(field, value)
|
||||||
|
} else if outFlag == "json" {
|
||||||
|
buildJSON(field, value)
|
||||||
|
} else {
|
||||||
|
return errors.New("invalid output option")
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func buildString(field, value string) {
|
||||||
|
if field != "" {
|
||||||
|
sb.WriteString(field)
|
||||||
|
sb.WriteString(":")
|
||||||
|
sb.WriteString(value)
|
||||||
|
sb.WriteString(sepFlag)
|
||||||
|
} else {
|
||||||
|
sb.WriteString(value)
|
||||||
|
sb.WriteString(sepFlag)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func buildJSON(field, value string) {
|
||||||
|
if field == "" {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
jsonMap[field] = value
|
||||||
|
}
|
||||||
Loading…
Reference in a new issue