用go实现linux命令行
来源:互联网 发布:sql视图是什么 编辑:程序博客网 时间:2024/04/19 00:58
用go实现linux命令行
要求:实现selpg命令,使用Go语言
以下为该命令参数形式
-s start_page -e end_page [ -f | -l lines_per_page ] [ -d dest ] [ in_filename ]
各参数意义如下
-s start page 表示打印开始的页数
-e end page 表示打印结束页数
-f 可选,表示文件是否以\f作为分页标志,与-l不能一起使用
-l 可选,表示文件几行作为一页,与-f不能一起使用
-d 可选,目标打印机
in_filename 可选,读入的文件,若不选则从标准流输入
A.关于实现过程个人觉得关键几个部分
1.关于字符串部分
根据老师教程是用os包获取命令行参数然后用flag包解析参数
这里os包只需简单调用os.Arg来获取参数即可,这里我们说一下flag包,flag包一般用来解析命令行参数
flag包主要包含一些方法和一个flagSet,后者只是对前者做了封装,这里我选择了用flagSet
/*函数原型*/func NewFlagSet(name string, errorHandling ErrorHandling) *FlagSet/*例子*/flagSet = flag.NewFlagSet(os.Args[0], flag.ExitOnError)
这是创建一个flagSet,其中第一个参数是程序名字,第二个是参数错误时的错误处理方法
这里os.Arg[0]是程序名字,然后我选择了错误时就终止程序的类型
接下来是定义几个参数
startPage = flagSet.Uint("s", 0, "tart_page, must be specified and greter than 0")endPage = flagSet.Uint("e", 0, "end_page, must be specified and greter than 0")pageLen = flagSet.String("l", "", "page_size, exclusive to -f, must be postive,default is 72")pageType = flagSet.Bool("f", false, "use \\f to divide pages, exclusive to -l")
以上的几个方法将会解析参数并将对应指针返回,对应的几个参数分别为参数的flag,参数默认值,参数描述
这是函数原型,创建flagSet对象后通过以上可方法定义参数
func Uint(name string, value uint, usage string) *uint
定义了参数后我们可以通过调用Parse方法,flagSet就会帮我们解析命令行内输入的字符串然后赋值给对应指针,如果用户写的参数错误就会按照你选择的错误方式处理
这里我还自定义了一种类型,flag中你可以通过Var等方法来给参数赋值自定义类型,但要实现Set()和String()两个接口用于赋值和转字符串
下面是我代码中的例子
type StringArray []stringfunc (s *StringArray) Set(value string) error { *s = append(*s, value) return nil}func (s *StringArray) String() string { return fmt.Sprint([]string(*s))}func (s *StringArray) Size() int { return len(*s)}func (s *StringArray) Top() (string, error) { if s.Size() > 0 { var temp = s.String() temp = strings.TrimSuffix(temp, "[") temp = strings.TrimSuffix(temp, "]") return temp, nil } return "", fmt.Errorf("empty error")}
根据官网文档建议
If you like, you can bind the flag to a variable using the Var() functions.
var flagvar int
func init() {
flag.IntVar(&flagvar, “flagname”, 1234, “help message for flagname”)
}
因此我在init函数里面对我的一个参数进行了定义
flagSet.Var(&printDest, "d", "destination")
剩下的就是获得参数后大概判断是不是合法参数,这些想必不是什么难点写写判断就可以
2.关于流和读取文件还有lp命令部分
关于流部分,首先要确定接受文件的流从哪输入过来
如果没有文件参数的话就是标准流,有的话就用文件流
var inputStream = os.Stdinif inputFile != "" { inputStream, err = os.Open(inputFile) defer inputStream.Close() if err != nil { fmt.Fprintf(os.Stderr, "%s : ", programname) fmt.Fprintln(os.Stderr, err) os.Exit(1) }}
这里使用os的open函数来打开文件流
然后关于这个流要输出到哪里,我们需要确定,如果存在目的打印机我们把我们读取的文件通过管道传到lp命令的输入流,这里我用bufio的reader来读文件,然后调用os/exec的StdinPipe()方法来将文件输入,当然如果用户没定义-d参数则将输出流输出到屏幕上即可
关键代码如下
stdin = os.Stdout if printDest.Size() > 0 && pDest != "" { printer = exec.Command("lp", "-d", pDest) //printer = exec.Command("cat") stdin, printErr = printer.StdinPipe() if printErr != nil { fmt.Fprintf(os.Stderr, "%s : ", programname) fmt.Fprintln(os.Stderr, printErr) } if *pageType { err = writeIntoPrintInByF(myReader, *startPage, *endPage) } else { err = writeIntoPrintInByLine(myReader, *startPage, *endPage, pLen) } if err != nil { fmt.Fprintf(os.Stderr, "%s : ", programname) fmt.Fprintln(os.Stderr, err) } stdin.Close()
然后这是将读取文件写入流中,这里我调用了Write方法
stdin.Write([]byte(line))
其中line是我调用reader的readString方法获得的字符串,当然也有其他库函数实现读取字符串
line, err := reader.ReadString('\n')
最后是启动命令,这里如果命令出错我们要杀进程,这里我用timer监听实现
printer.Stdout = os.Stdout printer.Stderr = os.Stderr if err = printer.Start(); err != nil { fmt.Fprintf(os.Stderr, "%s : ", programname) fmt.Fprintln(os.Stderr, printErr) } timer := time.AfterFunc(3*time.Second, func() { printer.Process.Kill() }) err = printer.Wait() timer.Stop()
3.关于源码
源码位于我的github:https://github.com/caijh23/Go/tree/master/selpg
代码分为两个文件args.go和slepg.go分别为上述讲的两个部分
4.结果展示
a.txt里面有两行数据均为123
这是没有打印机
这是输出到屏幕
这是参数错误
这是将lp命令换为cat的成功结果
- 用go实现linux命令行
- 用 Go 实现简单命令行实用程序 selpg
- Go语言实现Windows命令行下载文件.
- Go语言实现的命令行解析程序
- go实现命令行的工具cli
- go 命令行
- Go 用flag包解析命令行参数
- Go 命令行使用
- Go-命令行参数
- Go命令行工具
- Go-CLI 命令行实用程序
- Go命令行工具
- linux,go!
- Go解析命令行传入参数
- linux :vim 实现命令行下输出进度条
- Linux下GO语言内存共享,CGO实现
- 用WINRAR实现命令行解压
- 用GO实现的erlang的genfsm.
- ROS launch文件的作用和编写
- HDU 1074:Doing HomeWork(状态压缩DP)
- 顺序表应用2:多余元素删除之建表算法
- 求乘法逆元
- 禅道项目管理工具部署
- 用go实现linux命令行
- django manage.py扩展自定义命令
- ElasticSearch 5.1.1安装
- 简单的五子棋程序(可悔棋版和普通版)
- 仿真学习心得
- mysql学习之路09-触发器
- 两个数求和
- VS2015编译Python2.7.14源码(失败)
- C# Dictionary