Golang

2015-12-06 8 views
7
のフラグと引数にコマンドライン文字列を解析は

私は適切に引用符、スペース、などを扱う、-v --format "some example" -i testような文字列を取り、文字列のスライスにそれを解析しますパッケージを探しています:Golang

-v 
--format 
some example 
-i 
test 

組み込みのflagパッケージとGithubの他のフラグ処理パッケージをチェックしましたが、生の文字列をトークンに解析するこの特定のケースを処理していないようです。それを自分でしようとする前に、私はむしろパッケージのために特別なケースがたくさんあると確信しています。

提案がありますか?

+0

に分割されますショートフラグ形式)。私はこれらをパッケージにまとめている人は知らない。 – JimB

+0

迅速なハック(あなたが入力を提供する方法を変更することが柔軟である場合)になります( 'flag'パッケージのマニュアルを参照してください):\t \tセット:=&flag.FlagSet {} \t \t V:=セット.Bool( "v"、false、 "") \tフォーマット:= set.String( "format"、 ""、 "") \t i:= set.String( "i"、 ""、 "") \t \t set.Parse([]文字列{'-v'、' --format = "some example" '、' -i = test'}) \t k、v:= range set.Args() { \t \t log.Println(K、V) \t} \t ( "V =体積%形式=%VI =体積%"、* V、*形式、* I) –

+0

は私がもしわからない\t log.Printfわかりました。あなたは 'cmd -v --format"のような何かをするつもりですか? "-i test'?もしそうなら、あなたは 'os.Args'から全ての引数を取得できます。 – 425nesp

答えて

1

これは、私が作成した機能です。

コマンドを引数に分割します。たとえば、cat -v "some file.txt"は、["cat", "-v", "some file.txt"]を返します。

また、エスケープ文字、特にスペースも正しく処理します。だから、cat -v some\ file.txtも正しくこれは/シェルが何をするかの混合物(引用符で囲まれた文字列のグループ化)とGNUオプションの解析ツール(散在引数とフラグ、特定の動作と異なる長さであり["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 
}