douxiong5438 2015-12-06 14:53
浏览 326
已采纳

将命令行字符串解析为Golang中的标志和参数

I'm looking for a package that would take a string such as -v --format "some example" -i test and parse it into a slice of strings, handling quotes, spaces, etc. properly:

-v
--format
some example
-i
test

I've checked the built-in flag package as well as other flag handling packages on Github but none of them seem to handle this particular case of parsing a raw string into tokens. Before trying to do it myself I'd rather look for a package as I'm sure there are a lot of special cases to handle.

Any suggestion?

  • 写回答

3条回答 默认 最新

  • doushuo1080 2017-10-27 11:05
    关注

    For information, this is the function I've ended up creating.

    It splits a command into its arguments. For example, cat -v "some file.txt", will return ["cat", "-v", "some file.txt"].

    It also correctly handles escaped characters, spaces in particular. So cat -v some\ file.txt will also correctly be split into ["cat", "-v", "some file.txt"]

    func parseCommandLine(command string) ([]string, error) {
        var args []string
        state := "start"
        current := ""
        quote := "\""
        escapeNext := true
        for i := 0; i < len(command); i++ {
            c := command[i]
    
            if state == "quotes" {
                if string(c) != quote {
                    current += string(c)
                } else {
                    args = append(args, current)
                    current = ""
                    state = "start"
                }
                continue
            }
    
            if (escapeNext) {
                current += string(c)
                escapeNext = false
                continue
            }
    
            if (c == '\\') {
                escapeNext = true
                continue
            }
    
            if c == '"' || c == '\'' {
                state = "quotes"
                quote = string(c)
                continue
            }
    
            if state == "arg" {
                if c == ' ' || c == '\t' {
                    args = append(args, current)
                    current = ""
                    state = "start"
                } else {
                    current += string(c)
                }
                continue
            }
    
            if c != ' ' && c != '\t' {
                state = "arg"
                current += string(c)
            }
        }
    
        if state == "quotes" {
            return []string{}, errors.New(fmt.Sprintf("Unclosed quote in command line: %s", command))
        }
    
        if current != "" {
            args = append(args, current)
        }
    
        return args, nil
    }
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(2条)

报告相同问题?

悬赏问题

  • ¥15 程序不包含适用于入口点的静态Main方法
  • ¥15 素材场景中光线烘焙后灯光失效
  • ¥15 请教一下各位,为什么我这个没有实现模拟点击
  • ¥15 执行 virtuoso 命令后,界面没有,cadence 启动不起来
  • ¥50 comfyui下连接animatediff节点生成视频质量非常差的原因
  • ¥20 有关区间dp的问题求解
  • ¥15 多电路系统共用电源的串扰问题
  • ¥15 slam rangenet++配置
  • ¥15 有没有研究水声通信方面的帮我改俩matlab代码
  • ¥15 ubuntu子系统密码忘记