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 微信会员卡接入微信支付商户号收款
  • ¥15 如何获取烟草零售终端数据
  • ¥15 数学建模招标中位数问题
  • ¥15 phython路径名过长报错 不知道什么问题
  • ¥15 深度学习中模型转换该怎么实现
  • ¥15 HLs设计手写数字识别程序编译通不过
  • ¥15 Stata外部命令安装问题求帮助!
  • ¥15 从键盘随机输入A-H中的一串字符串,用七段数码管方法进行绘制。提交代码及运行截图。
  • ¥15 TYPCE母转母,插入认方向
  • ¥15 如何用python向钉钉机器人发送可以放大的图片?