Support backslash-escaped slashes in find-and-replace substitution. (#1699)

This commit is contained in:
Victor Shih 2016-07-09 10:37:13 -07:00 committed by Brad Rydzewski
parent 324392d3e0
commit 7188e1d410
2 changed files with 24 additions and 8 deletions

View file

@ -96,24 +96,34 @@ func substituteDefault(str, key, val string) string {
return str
}
// unescapeBackslash is a helper function to unescape any backslashes in str.
// Note that no actual literal conversions are done.
func unescapeBackslash(str string) string {
re := regexp.MustCompile(`\\(.)`)
return string(re.ReplaceAll([]byte(str), []byte("$1")))
}
// substituteReplace is a helper function that substitutes paramters using
// ${parameter/old/new} notation with the parameter value. A find and replace
// is performed before injecting the strings, replacing the old pattern with
// the new value.
func substituteReplace(str, key, val string) string {
key = fmt.Sprintf("\\${%s/(.+)/(.+)}", key)
key = fmt.Sprintf(`\${%s/((?:\\.|[^\\])+)/(.+)}`, key)
reg, err := regexp.Compile(key)
if err != nil {
return str
}
for _, match := range reg.FindAllStringSubmatch(str, -1) {
if len(match) != 3 {
continue
}
with := strings.Replace(val, match[1], match[2], -1)
str = strings.Replace(str, match[0], with, -1)
match := reg.FindStringSubmatch(str)
if match == nil {
return str
}
return str
old := unescapeBackslash(match[1])
new := unescapeBackslash(match[2])
with := strings.Replace(val, old, new, -1)
return strings.Replace(str, match[0], with, -1)
}
// substituteLeft is a helper function that substitutes paramters using

View file

@ -53,6 +53,12 @@ func TestSubstitution(t *testing.T) {
g.Assert(substituteReplace(before, "GREETING", "HELLO")).Equal(after)
})
g.It("Should substitute parameters with replacement, containing slashes", func() {
before := `echo ${GREETING/HE\//A} MONDE`
after := "echo ALLO MONDE"
g.Assert(substituteReplace(before, "GREETING", "HE/LLO")).Equal(after)
})
g.It("Should substitute parameters with left substr", func() {
before := "echo ${FOO:4} IS COOL"
after := "echo THIS IS COOL"