package main import ( "flag" "os" "strings" "gopkg.in/yaml.v3" ) var ( input = stringsArray{} output = "" indent = 2 replaceArrays = false ) func main() { flag.Var(&input, "i", "input files") flag.StringVar(&output, "o", "out.yaml", "output file") flag.IntVar(&indent, "indent", 2, "changes the used indentation used when encoding") flag.BoolVar(&replaceArrays, "replace_arrays", false, "replace arrays with same keys. Merge otherwise.") flag.Parse() result := map[string]any{} for _, inputFile := range input { b, err := os.ReadFile(inputFile) if err != nil { panic(err) } m := map[string]any{} if err := yaml.Unmarshal(b, m); err != nil { panic(err) } merge(result, m, replaceArrays) } fp, err := os.Create(output) if err != nil { panic(err) } defer fp.Close() enc := yaml.NewEncoder(fp) enc.SetIndent(indent) if err := enc.Encode(result); err != nil { panic(err) } } func merge(target map[string]any, in map[string]any, replaceArrays bool) { for k, v := range in { old, exist := target[k] if !exist { target[k] = v continue } switch old := old.(type) { case map[string]any: v, ok := v.(map[string]any) if ok { merge(old, v, replaceArrays) target[k] = old continue } case []any: v, ok := v.([]any) if ok && !replaceArrays { old = append(old, v...) target[k] = old continue } } target[k] = v } } type stringsArray []string func (i *stringsArray) Set(value string) error { *i = append(*i, value) return nil } func (i *stringsArray) String() string { return strings.Join(*i, ",") }