【问题标题】:How to get os.Args-like tokens from a command line string如何从命令行字符串中获取类似 os.Args 的标记
【发布时间】:2017-09-18 02:24:00
【问题描述】:

我有一个字符串变量:

commandLineString := `echo -n "a b c d"`

我想把它转换成:

args := []string{"echo", "-n", "\"a b c d\""}

我该怎么做?

【问题讨论】:

标签: string go token string-parsing


【解决方案1】:

如果字符串修复有 3 个参数,您可以通过 strings.SplitN 完成。这是关于 golang 字符串库的完整文档。 https://golang.org/pkg/strings/#SplitN

CMIIW ^^

【讨论】:

  • 如何保留带引号的字符串?
  • @md2perpe 使用SplitN() 按空格分割,将最大分割指定为 3,因此第二个空格之后的子字符串将不再分割.. 仅使用固定数量的参数,并且仅使用最后一个参数可以包含空间。无论如何,这适用于 OP 的特定样本..
【解决方案2】:

这可以使用regular expression 以非常紧凑的方式表达。

输入(命令)是一系列标记,它们是:

  1. 不带引号且不能包含引号和空格,
  2. 或引用并生成直到下一个引号,并且可以包含空格(但不能包含引号)。

还有:

  1. 标记用空格或输入结尾分隔。

来自所列条件的正则表达式:

           ("[^"]*"|[^"\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 上试试这些。

【讨论】:

  • 这种方法有几个问题:首先,它包含带引号参数的引号,而 os.Args 没有,并且需要使用它的代码来处理它们;其次,它不考虑参数中的转义引号。
  • @Adrian 它不包括带引号参数的引号,这只是我使用%q 动词打印它以确保它们存在的方式。用%v 打印它,你会看到它们是正常的引号。
  • 不适用于 curl 这样的命令,它甚至需要 JSON 数据
猜你喜欢
  • 2022-01-05
  • 2014-07-17
  • 1970-01-01
  • 2011-03-08
  • 2020-08-20
  • 2019-03-21
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多