60 lines
1.2 KiB
Go
60 lines
1.2 KiB
Go
|
package main
|
||
|
|
||
|
import (
|
||
|
"fmt"
|
||
|
"strings"
|
||
|
"unicode"
|
||
|
)
|
||
|
|
||
|
const NullStr = rune(0)
|
||
|
|
||
|
// ParseArgs will parse a string that contains quoted strings the same as bash does
|
||
|
// (same as most other *nix shells do). This is secure in the sense that it doesn't do any
|
||
|
// executing or interpeting. However, it also doesn't do any escaping, so you shouldn't pass
|
||
|
// these strings to shells without escaping them.
|
||
|
func ParseArgs(str string) ([]string, error) {
|
||
|
var m []string
|
||
|
var s string
|
||
|
|
||
|
str = strings.TrimSpace(str) + " "
|
||
|
|
||
|
lastQuote := NullStr
|
||
|
isSpace := false
|
||
|
for i, c := range str {
|
||
|
switch {
|
||
|
// If we're ending a quote, break out and skip this character
|
||
|
case c == lastQuote:
|
||
|
lastQuote = NullStr
|
||
|
|
||
|
// If we're in a quote, count this character
|
||
|
case lastQuote != NullStr:
|
||
|
s += string(c)
|
||
|
|
||
|
// If we encounter a quote, enter it and skip this character
|
||
|
case unicode.In(c, unicode.Quotation_Mark):
|
||
|
isSpace = false
|
||
|
lastQuote = c
|
||
|
|
||
|
// If it's a space, store the string
|
||
|
case unicode.IsSpace(c):
|
||
|
if 0 == i || isSpace {
|
||
|
continue
|
||
|
}
|
||
|
isSpace = true
|
||
|
m = append(m, s)
|
||
|
s = ""
|
||
|
|
||
|
default:
|
||
|
isSpace = false
|
||
|
s += string(c)
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
if lastQuote != NullStr {
|
||
|
return nil, fmt.Errorf("Quotes did not terminate")
|
||
|
}
|
||
|
|
||
|
return m, nil
|
||
|
}
|