github.com/ActiveState/cli@v0.0.0-20240508170324-6801f60cd051/internal/osutils/shellescape.go (about) 1 package osutils 2 3 import ( 4 "regexp" 5 "strings" 6 ) 7 8 // ShellEscape serve to escape arguments passed to shell commands 9 type ShellEscape struct { 10 wordPattern *regexp.Regexp 11 escapePattern *regexp.Regexp 12 escapeWith string 13 } 14 15 //NewBashEscaper creates a new instance of ShellEscape that's configured for escaping bash style arguments 16 func NewBashEscaper() *ShellEscape { 17 return &ShellEscape{ 18 regexp.MustCompile(`^[\w]+$`), 19 regexp.MustCompile(`(\\|"|\$)`), 20 `\$1`, 21 } 22 } 23 24 // NewBatchEscaper creates a new instance of ShellEscape that's configured for escaping batch style arguments 25 func NewBatchEscaper() *ShellEscape { 26 return &ShellEscape{ 27 regexp.MustCompile(`^[\w]+$`), 28 regexp.MustCompile(`"`), 29 `""`, 30 } 31 } 32 33 // NewCmdEscaper creates a new instance of ShellEscape that's configured for escaping cmd arguments 34 func NewCmdEscaper() *ShellEscape { 35 return &ShellEscape{ 36 regexp.MustCompile(`^[^ &()\[\]{}^=;!'+,~]+$`), // cmd.exe /? lists these characters as requiring quotes 37 regexp.MustCompile(`"`), 38 `""`, 39 } 40 } 41 42 // EscapeLineEnd will escape any line end characters that require escaping for the purpose of quoting 43 func (s *ShellEscape) EscapeLineEnd(value string) string { 44 value = strings.Replace(value, "\n", `\n`, -1) 45 value = strings.Replace(value, "\r", `\r`, -1) 46 return value 47 } 48 49 // Escape will escape any characters that require escaping for the purpose of quoting 50 func (s *ShellEscape) Escape(value string) string { 51 return s.escapePattern.ReplaceAllString(value, s.escapeWith) 52 } 53 54 // Quote implements SubShell.Quote 55 func (s *ShellEscape) Quote(value string) string { 56 if len(value) == 0 { 57 return `""` 58 } 59 if s.wordPattern.MatchString(value) { 60 return value 61 } 62 return `"` + s.EscapeLineEnd(s.Escape(value)) + `"` 63 }