func ReplaceFormatted(s string, kv map[string]interface{}) (string, error) {
	wanted := make([]string, 0)

	for m := re.FindStringSubmatch(s); m != nil; m = re.FindStringSubmatch(s) {
		match, key, format := m[0], m[1], m[3]

		// find key and replacement value
		val, ok := kv[key]
		if !ok {
			wanted = append(wanted, key)
			format = "%s"
			val = "?"
		}

		// update all literal matches
		new := FormatValue(format, val)
		s = strings.ReplaceAll(s, match, new)
	}

	// return missing keys
	var err error
	if len(wanted) > 0 {
		got := make([]string, 0)
		for k := range kv {
			got = append(got, k)
		}

		err = fmt.Errorf("wanted: %v, got: %v", wanted, got)
	}

	return s, err
}
// ReplaceFormatted replaces all occurrences of ${key} with formatted val from the kv map
ReplaceFormatted replaces all occurrences of ${key} with formatted val from the kv map
// ReplaceFormatted replaces all occurrences of $ { key } with formatted val from the kv map
func ReplaceFormatted(s string, kv map[string]interface{}) (string, error) {
	wanted := make([]string, 0)
	for m := re.FindStringSubmatch(s); m != nil; m = re.FindStringSubmatch(s) {
		match, key, format := m[0], m[1], m[3]
		val, ok := kv[key]
		if !ok {
			wanted = append(wanted, key)
			format = "%s"
			val = "?"
		}
		new := FormatValue(format, val)
		s = strings.ReplaceAll(s, match, new)
	}
	var err error
	if len(wanted) > 0 {
		got := make([]string, 0)
		for k := range kv {
			got = append(got, k)
		}
		err = fmt.Errorf("wanted: %v, got: %v", wanted, got)
	}
	return s, err
}
func ReplaceFormatted ( s string , kv map [ string ] interface { } ) ( string , error ) { wanted := make ( [ ] string , 0 ) for m := re . FindStringSubmatch ( s ) ; m != nil ; m = re . FindStringSubmatch ( s ) { match , key , format := m [ 0 ] , m [ 1 ] , m [ 3 ] val , ok := kv [ key ] if ! ok { wanted = append ( wanted , key ) format = " " val = " " } new := FormatValue ( format , val ) s = strings . ReplaceAll ( s , match , new ) } var err error if len ( wanted ) > 0 { got := make ( [ ] string , 0 ) for k := range kv { got = append ( got , k ) } err = fmt . Errorf ( " " , wanted , got ) } return s , err }
ReplaceFormatted replaces all occurrences of ${key} with formatted val from the kv map
ReplaceFormatted replaces all occurrences of $ { key } with formatted val from the kv map
// find key and replacement value // update all literal matches // return missing keys