本次作业参考潘老师的博客
https://pmlpml.github.io/ServiceComputingOnCloud/ex-cli-basic
github传送门
https://github.com/ddghost/Sevice-Computing/tree/CLI-命令行实用程序开发基础
本次作业主要是编写一个命令行程序,处理标准输入或者文本文件。程序的要求主要参考、https://www.ibm.com/developerworks/cn/linux/shell/clutil/index.html
对于命令行程序,首先要做的就是解析命令行传入的参数,例如执行程序
./selpag -s 1 -e 1 input.txt
对于这个命令,我们这个程序应该要至少有三个变量,一个记录-s后的1,一个记录-e后的1,一个记录input.txt。
传入的参数是命令行程序最重要的东西。解析可以使用os库里的os.Args,但是这很麻烦。
所幸已经有前人帮我们完成解析参数的工作,那就是使用flag或者pflag库。这两个库的使用可以参考
https://o-my-chenjian.com/2017/09/20/Using-Flag-And-Pflag-With-Golang/
在命令行输入以下代码获得pflag包,而flag包不用获取
go get github.com/spf13/pflag
由于老师要求使用pflag,这里给出pflag简单的代码使用,例如对于IntVarP,五个参数分别是,变量的地址,长名,短名,默认值,帮助时的语句。
flag.IntVarP(&page_len , "l", "l" , 72, "page length")
flag.BoolVarP(&help , "h", "h", false, "show help")
flag.StringVarP(&print_dest , "d", "d" , "", "print detination")
对于传入的参数,以下两种情况是等价的,它们都会把page_len赋值为11。
./selpage -l 11
./selpage -l=11
./selpage --l 11
./selpage --l=11
将变量名和传入的参数绑定后,使用parse就可以解析了,注意不要忘了,否则忘了解析各变量的值都是默认的。
flag.parse()
对于传入的前面是‘-’的参数,可以用pflag提前绑定好变量,但是这次传入的文件名参数,前面是没有‘-’的,这里只要注意 pflag 会把不能解析的参数都放在Args()数组里面,因此调用flag.Args()[0]就可以获得第一个没被解析成flag的参数,也就是文件名。
在实现要求中,展示了程序在命令行中搭配’<’ , ‘>’ , ‘|’ 符号的操作,我对命令行的操作并不是太熟悉,开始还很奇怪为什么输入之后用pflag解析不了。
后来发现这些符号的效果并不需要我们实现,它们是linux命令行自带的效果,和‘&’符号一样。
本部分参考
https://godoc.org/os/exec#example-Command
在本次作业中,需要在程序里执行一个命令行的命令lp,因此要用到os/exec包,简要的代码如下。
exec.Command后面的传入的参数就是命令行要执行的命令还有参数,例如想执行“cat tmp.txt“,就应该传入"cat"和 “tmp.txt”,简单来说就是将空格分开的部分分别写进去。
然后cmd.StdinPipe()就是lp命令的输入管道,lp的输入接受本程序的输出。
然后后面cmd.Start执行命令行程序。
如果3秒后还没执行完,进行终止。
cmd = exec.Command("lp" , "-d" , print_dest)
fout, err = cmd.StdinPipe()
if err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}
outputFile(inputFile , fout)
fout.Close()
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
err = cmd.Start()
if err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}
timer := time.AfterFunc(3*time.Second, func() {
cmd.Process.Kill()
})
err = cmd.Wait()
timer.Stop()
还记得老师布置作业的时候说这次作业很简单,很快就能写完,但是在国庆的时候我花了好几天才写完,光是文档都看了好久。最主要的问题还是对linux命令行很多东西都不是太熟悉,还有第一次写go程序也不太熟练的缘故。