mirror of
https://github.com/octoleo/restic.git
synced 2024-06-03 09:30:50 +00:00
74 lines
1.5 KiB
Go
74 lines
1.5 KiB
Go
|
package sftp
|
||
|
|
||
|
import (
|
||
|
"errors"
|
||
|
"unicode"
|
||
|
)
|
||
|
|
||
|
const data = `"foo" "bar" baz "test argument" another 'test arg' "last \" argument" 'another \" last argument'`
|
||
|
|
||
|
// shellSplitter splits a command string into separater arguments. It supports
|
||
|
// single and double quoted strings.
|
||
|
type shellSplitter struct {
|
||
|
quote rune
|
||
|
lastChar rune
|
||
|
}
|
||
|
|
||
|
func (s *shellSplitter) isSplitChar(c rune) bool {
|
||
|
// only test for quotes if the last char was not a backslash
|
||
|
if s.lastChar != '\\' {
|
||
|
|
||
|
// quote ended
|
||
|
if s.quote != 0 && c == s.quote {
|
||
|
s.quote = 0
|
||
|
return true
|
||
|
}
|
||
|
|
||
|
// quote starts
|
||
|
if s.quote == 0 && (c == '"' || c == '\'') {
|
||
|
s.quote = c
|
||
|
return true
|
||
|
}
|
||
|
}
|
||
|
|
||
|
s.lastChar = c
|
||
|
|
||
|
// within quote
|
||
|
if s.quote != 0 {
|
||
|
return false
|
||
|
}
|
||
|
|
||
|
// outside quote
|
||
|
return c == '\\' || unicode.IsSpace(c)
|
||
|
}
|
||
|
|
||
|
// SplitShellArgs returns the list of arguments from a shell command string.
|
||
|
func SplitShellArgs(data string) (list []string, err error) {
|
||
|
s := &shellSplitter{}
|
||
|
|
||
|
// derived from strings.SplitFunc
|
||
|
fieldStart := -1 // Set to -1 when looking for start of field.
|
||
|
for i, rune := range data {
|
||
|
if s.isSplitChar(rune) {
|
||
|
if fieldStart >= 0 {
|
||
|
list = append(list, data[fieldStart:i])
|
||
|
fieldStart = -1
|
||
|
}
|
||
|
} else if fieldStart == -1 {
|
||
|
fieldStart = i
|
||
|
}
|
||
|
}
|
||
|
if fieldStart >= 0 { // Last field might end at EOF.
|
||
|
list = append(list, data[fieldStart:])
|
||
|
}
|
||
|
|
||
|
switch s.quote {
|
||
|
case '\'':
|
||
|
return nil, errors.New("single-quoted string not terminated")
|
||
|
case '"':
|
||
|
return nil, errors.New("double-quoted string not terminated")
|
||
|
}
|
||
|
|
||
|
return list, nil
|
||
|
}
|