服务计算——开发简单的CLI程序
代码请看github
根据Linux命令行上的Selpg指令,结合Flag和PFlag利用go语言开发简单的CLI程序
-
论述
- 按照上述链接的说明,Linux命令行通过默认或指定参数调用指令,其中指定参数中使用
Flag
中方法,通过类似-a10
的方式a
对应参数赋值为10
,而PFlag方法则为相应的变形,变为诸如--a=10
的方式为参数赋值。通过类似的方法,利用PFlag构建简单的读取文件命令指令。
- 按照上述链接的说明,Linux命令行通过默认或指定参数调用指令,其中指定参数中使用
-
代码
-
构建参数的
Help
指令,指导用户如何传入参数调用指令。其中,根据PFlag
中的IntVar、StringVar
函数,构建相应的命令,其后调用Parse
函数解析上述Help
指令即如下代码:func set_flag(){ pflag.IntVar(&(start_page), "s", -1, "Define start page, defaults to -1") pflag.IntVar(&(end_page), "e", -1, "Define end page, defaults to -1") pflag.IntVar(&(page_len), "l", 1, "Define page length, defaults to 1") pflag.StringVar(&(in_file), "i", "in_file.txt", "Define input file's name, defaults to in_file.txt") pflag.StringVar(&(print_des), "d", "", "Define input file's name, defaults to NULL") //pflag.StringVar(&(err_des), "e", "../errpr_file.txt", "Define input file's name, defaults to errpr_file.txt") pflag.Parse() } ```
-
由于按照需求,需要进一步对参数进行处理,即根据传入的参数指令配置相关变量信息,根据
os.Args
参数处理。func check_args_1(args []string) { for _, para := range args[1:] { switch{ case para[0:2] == "--s", para[0:2] == "--e": if val, err := strconv.Atoi(para[4:]); err != nil || val < 0{ if err != nil{ fmt.Fprintf(os.Stderr, fmt.Sprintf("%s",err)) }else{ fmt.Fprintf(os.Stderr, "\n[Error] The start/end page can not less then zero or be empty\n") } os.Exit(2) } case para[0:2] == "--l": if val, err := strconv.Atoi(para[4:]); err != nil || val < 0{ if err != nil{ fmt.Fprintf(os.Stderr, fmt.Sprintf("%s",err)) }else{ fmt.Fprintf(os.Stderr, "\n[Error] The page lenth can not less then zero\n") } os.Exit(3) } case para[0:2] == "--i": if file, err := os.Open(para[4:]); err != nil { fmt.Fprintf(os.Stderr, fmt.Sprintf("%s",err)) os.Exit(4) }else{ file.Close() } case para[0] == '<', para[0] == '>': if file, err := os.Open(para[1:]); err != nil { fmt.Fprintf(os.Stderr, fmt.Sprintf("%s",err)) os.Exit(4) }else{ if para[0] == '<'{ in_file = para[1:] }else{ print_des = para[1:] } file.Close() } } } }
-
初步处理完参数后,还需要进一步检查参数即判断
start_page、end_page
的关系。func check_args_2(){ if selpg.start_page > selpg.end_page { fmt.Fprintf(os.Stderr, "\n[Error] The start page should larger than the end page\n") os.Exit(5) } }
-
配置相关
selpg
类,保存上述获取的参数信息。type Selpg struct{ start_page int end_page int page_len int in_file string print_des string err_des string }
-
根据上述获得的参数信息,进行命令的处理,即为是否从指定路径读取文件,是否向指定路径写文件以及读取的行数以及起始终止位置等。
func process(){ var outfile *os.File if selpg.print_des != ""{ if _,err_exit := os.Stat(selpg.print_des); err_exit != nil { outfile,_= os.Create(selpg.print_des) }else{ outfile, _ = os.OpenFile(selpg.print_des,os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0666) } } defer outfile.Close() if selpg.in_file != ""{ var infile *os.File infile, _ = os.OpenFile(selpg.in_file, os.O_RDWR, 0666) defer infile.Close() buf := bufio.NewReader(infile) page_count := 1 line_count := 0 for page_count <= selpg.end_page { line, in_err := buf.ReadString('\n') if in_err != nil { fmt.Fprintf(os.Stderr, fmt.Sprintf("%s",in_err)) os.Exit(7) } if in_err == io.EOF{ break } if page_count >= selpg.start_page{ if selpg.print_des != ""{ outfile.Write([]byte(line)) }else{ fmt.Println(line) } } line_count++ if line_count == selpg.page_len { line_count = 0 page_count++ } } } }
-
传入指令,在未指定输出文件下输出不同的
s、e
参数值,其输出内容如下:
- 当使用
d
参数指定输出文件时,终端输出以及相应文件输出内容分别如下:
- 当命令行输入错误或未输入必要的参数时,输出相应的
Help
信息。
- 通过
>
指定输出文件后,终端和文件输出内容分别如下。
- 通过比较可以看出,当
>
传入参数时,Ubuntu终端也会解析指令,从而将原有的关于PFlag
参数信息输出到相应位置。
-