Chinaunix首页 | 论坛 | 博客
  • 博客访问: 3844439
  • 博文数量: 146
  • 博客积分: 3918
  • 博客等级: 少校
  • 技术积分: 8584
  • 用 户 组: 普通用户
  • 注册时间: 2010-10-17 13:52
个人简介

个人微薄: weibo.com/manuscola

文章分类

全部博文(146)

文章存档

2016年(3)

2015年(2)

2014年(5)

2013年(42)

2012年(31)

2011年(58)

2010年(5)

分类: LINUX

2013-11-16 23:42:07

    上一篇博文学习了获取环境变量和入参的方法,但是实际应用中,入参要复杂一些,现实世界,绝不会仅仅让你打印大
    我们随便写一个日常使用的psql的命令行用法
  1. manu@manu-hacks:~$ pg_ctl -D /home/manu/DB_data/ -l /home/manu/DB_data/postgres_manu.log   start 
  2. server starting
    这种情况下我们更需要的是解析各个参数的意义,比如-D选项 是通知pg_ctl pgdata的路径在那,-l选项告知的是log记录到那个文件,start相当于子命令,告知action。对于这种命令,我们都知道C语言有getopt及其getopt_long来解决。go语言怎么解决?
    go语言提供了flag这个package。来应对这种入参的解析。
    flag支持的语言格式如下:
  •     -flag     // bool类型only
  •     -flag=x
  •     -flag x  //not bool 类型
    很自然,这个flag能够解析 -D /home/manu/DB_data,对应第二种类型,我们知道pg_ctl有-W选项,属于一个开关性质的bool型的选项
  1. -W do not wait until operation completes
自然对应第一种类型,也可以解析。第二种也很好理解。
    下面我给出一个例子,简单的解析这个pg_ctl的命令:
  1. manu@manu-hacks:~/code/go/self$ cat pg_ctl_parse.go 


  2. package main
  3. import (
  4.     "fmt"
  5.     "flag"
  6. )

  7. func main(){

  8.     data_path := flag.String("D","/home/manu/sample/","DB data path")
  9.     log_file := flag.String("l","/home/manu/sample.log","log file")
  10.     nowait_flag :=flag.Bool("W",false,"do not wait until operation completes")

  11.     flag.Parse()

  12.     var cmd string = flag.Arg(0);

  13.     fmt.Printf("action   : %s\n",cmd)
  14.     fmt.Printf("data path: %s\n",*data_path)
  15.     fmt.Printf("log file : %s\n",*log_file)
  16.     fmt.Printf("nowait     : %v\n",*nowait_flag)

  17.     fmt.Printf("-------------------------------------------------------\n")

  18.     fmt.Printf("there are %d non-flag input param\n",flag.NArg())
  19.     for i,param := range flag.Args(){
  20.         fmt.Printf("#%d    :%s\n",i,param)
  21.     }


  22. }
    OK,我们分析下代码(分割线下面的我们暂时不看):
    第一行对应的是data_path的解析规则
    -D选项对应的值是字符串类型字符串,
    默认值是“/home/manu/sample”,
    DB data path提示信息或者help信息或者说明是。

  1. manu@manu-hacks:~/code/go/self$ go run pg_ctl_parse.go  -D /home/manu/DB_data/ -l /home/manu/DB_data/postgres_manu.log -W start
    action   : start
    data path: /home/manu/DB_data/
    log file : /home/manu/DB_data/postgres_manu.log
    nowait : true
    -------------------------------------------------------
    there are 1 non-flag input param
    #0 :start

    manu@manu-hacks:~/code/go/self$ go run pg_ctl_parse.go   -l=/home/manu/DB_data/postgres_manu.log -W -D /home/manu/DB_data/  start
    action   : start
    data path: /home/manu/DB_data/
    log file : /home/manu/DB_data/postgres_manu.log
    nowait : true
    -------------------------------------------------------
    there are 1 non-flag input param
    #0 :start

    我们看到了,解析出了data_path,log_file无论 -l -D出现的顺序如何,只要正常的出现了,就能正常的解析。
    但是晴朗的天空中也有一片乌云,start不是这种 -key=alue 或则-option的类型,flag是解析不了的。我们称这种参数为non-flag参数,flag解析遇到non-flag参数就停止了:
  1. s := f.args[0]
  2. if len(s) == 0 || s[0] != '-' || len(s) == 1 {
  3.     return false, nil
  4. }
    所以如果我们将non-flag参数放在最前面,flag什么也不会解析,因为flag遇到了这个就停止解析了。
  1. manu@manu-hacks:~/code/go/self$ go run pg_ctl_parse.go  start -l=/home/manu/DB_data/postgres_manu.log -W -D /home/manu/DB_data/  
    action   : start
    data path: /home/manu/sample
    log file : /home/manu/sample.log
    nowait   : false
    -------------------------------------------------------
    there are 5 non-flag input param
    #0 :start
    #1 :-l=/home/manu/DB_data/postgres_manu.log
    #2 :-W
    #3 :-D
    #4 :/home/manu/DB_data/


    OK,flag提供了Arg(i),Args()来获取non-flag参数,NArg()来获取non-flag的个数。正如我们们sample 代码看到的。    
  1. fmt.Printf("there are %d non-flag input param\n",flag.NArg())
  2.     for i,param := range flag.Args(){
  3.         fmt.Printf("#%d :%s\n",i,param)
  4.     }
    flag还提供了NFlag()获取那些匹配上的参数的个数。
    从例子上看,flag package很有用,但是并没有强大到解析一切的程度。
    如果你有类似-option或者-key =value这种参数,不妨试试 flag。如果你的入参解析非常复杂,flag可能捉襟见肘。

参考文献:
标准库—命令行参数解析flag


阅读(25099) | 评论(0) | 转发(1) |
给主人留下些什么吧!~~