62 lines
1.3 KiB
Go
62 lines
1.3 KiB
Go
package cmd
|
|
|
|
import (
|
|
"regexp"
|
|
"strings"
|
|
)
|
|
|
|
// nonShellLiteralRx is a regular expression that matches anything that is not a
|
|
// shell literal.
|
|
var nonShellLiteralRx = regexp.MustCompile(`[^+\-./0-9=A-Z_a-z]`)
|
|
|
|
// shellQuote returns s quoted as a shell argument, if necessary.
|
|
func shellQuote(s string) string {
|
|
const (
|
|
backslash = '\\'
|
|
singleQuote = '\''
|
|
)
|
|
|
|
switch {
|
|
case s == "":
|
|
return "''"
|
|
case nonShellLiteralRx.MatchString(s):
|
|
result := make([]byte, 0, 2+len(s))
|
|
inSingleQuotes := false
|
|
for _, b := range []byte(s) {
|
|
switch b {
|
|
case singleQuote:
|
|
if inSingleQuotes {
|
|
result = append(result, singleQuote)
|
|
inSingleQuotes = false
|
|
}
|
|
result = append(result, backslash, singleQuote)
|
|
default:
|
|
if !inSingleQuotes {
|
|
result = append(result, singleQuote)
|
|
inSingleQuotes = true
|
|
}
|
|
result = append(result, b)
|
|
}
|
|
}
|
|
if inSingleQuotes {
|
|
result = append(result, singleQuote)
|
|
}
|
|
return string(result)
|
|
default:
|
|
return s
|
|
}
|
|
}
|
|
|
|
// shellQuoteCommand returns a string containing command and args shell quoted.
|
|
func shellQuoteCommand(command string, args []string) string {
|
|
if len(args) == 0 {
|
|
return shellQuote(command)
|
|
}
|
|
elems := make([]string, 1+len(args))
|
|
elems[0] = shellQuote(command)
|
|
for i, arg := range args {
|
|
elems[i+1] = shellQuote(arg)
|
|
}
|
|
return strings.Join(elems, " ")
|
|
}
|