这可以使用regular expression 以非常紧凑的方式表达。
输入(命令)是一系列标记,它们是:
- 不带引号且不能包含引号和空格,
- 或引用并生成直到下一个引号,并且可以包含空格(但不能包含引号)。
还有:
- 标记用空格或输入结尾分隔。
来自所列条件的正则表达式:
("[^"]*"|[^"\s]+)(\s+|$)
Criteria: __2____ __1___ __3__
使用 Go 的 regexp 包解决方案很短:
s := `echo -n "a b c d"`
pattern := `("[^"]*"|[^"\s]+)(\s+|$)`
r := regexp.MustCompile(pattern)
fmt.Printf("%q\n", r.FindAllStringSubmatch(s, -1))
fmt.Printf("%q\n", r.FindAllString(s, -1))
输出(在Go Playground上试试):
[["echo " "echo" " "] ["-n " "-n" " "] ["\"a b c d\"" "\"a b c d\"" ""]]
["echo " "-n " "\"a b c d\""]
请注意,regexp.FindAllString() 的结果还包含标记之间的分隔符(空格),因此您可以在它们上调用 strings.TrimSpace() 以删除它们:
ss := r.FindAllString(s, -1)
out1 := make([]string, len(ss))
for i, v := range ss {
out1[i] = strings.TrimSpace(v)
}
fmt.Printf("%q\n", out1)
提供所需的输出:
["echo" "-n" "\"a b c d\""]
或者你可以使用regexp.FindAllStringSubmatch()的结果:它返回一个切片,使用每个元素的第二个元素(索引1):
sss := r.FindAllStringSubmatch(s, -1)
out2 := make([]string, len(sss))
for i, v := range sss {
out2[i] = v[1]
}
fmt.Printf("%q\n", out2)
这也给出了所需的输出:
["echo" "-n" "\"a b c d\""]
在Go Playground 上试试这些。