Парсить командную строку в флаги и аргументы в Golang
Я ищу пакет, который будет принимать строку типа -v --format "some example" -i test
и разберите его на фрагмент строк, обрабатывая кавычки, пробелы и т. д. правильно:
-v
--format
some example
-i
test
Я проверил встроенный flag
пакет, а также другие пакеты обработки флагов на Github, но ни один из них, похоже, не обрабатывает этот конкретный случай разбора необработанной строки на токены. Прежде чем пытаться сделать это сам, я бы предпочел искать пакет, поскольку я уверен, что есть много особых случаев ручка.
любое предложение?
2 ответов
для информации, это функция, которую я в конечном итоге создал.
он разбивает команду на его аргументы. Например, cat -v "some file.txt"
вернет ["cat", "-v", "some file.txt"]
.
Он также правильно обрабатывает экранированные символы, в частности пробелы. Так что cat -v some\ file.txt
также будет правильно разбит на ["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
}
Если args были переданы вашей программе в командной строке, то оболочка должна обрабатывать это и os.Args
будет заполнено правильно. Например, в вашем случае os.Args[1:]
будет равна
[]string{"-v", "--format", "some example", "-i", "test"}
Если у вас просто есть строка, по какой-то причине, и вы хотели бы имитировать то, что оболочка будет делать с ней, тогда я рекомендую пакет, такой как https://github.com/kballard/go-shellquote