实现:github
前言
本文介绍了使用GO语言实现Selpg这样一个程序的过程,总体参考了开发Linux命令行实用程序这篇文章,它讲的是使用C语言实现Selpg。Selpg即Select Pages,允许用户指定从输入文本(可来自文件或命令行或是另一个进程的输出)抽取的页的范围,并控制输出的位置,可以是标准输出,也可以输入至文件或子进程。
Usage
1 | Usage: selpg [-s startPage] [-e endPage] [-l linesPerPage | -f] [-d printDest] filename |
代码结构
总共有三个函数:
main函数:解析命令参数的入口函数
processArgs函数:处理参数,进行错误处理
processInput函数:经过processArgs函数后,这里根据命令进行(文件)操作
除此之外,还有保存参数的struct:selpgArgs,以及五个解析参数用的flag。
selpgArgs存储内容:
1 | type selpgArgs struct { |
关键实现
- pflag
在前面的参考文章中,可以看到如果使用C语言来解析参数,代码实现还是比较繁杂的,需要手动进行参数的获取、判断乃至解析。而在Go语言中,有很多便利的包供我们使用,在这里使用的是pflag这个包来进行参数的解析。
pflag包的使用是非常简单的,首先go get
了这个包(spf13/pflag)之后,引入它就可以使用了。基本的参数绑定操作:
1 | var ip *int = flag.Int("flagname", 1234, "help message for flagname") //绑定"--flagname"的值到*ip上,格式为int |
在Selpg中,我们需要两种格式的参数,拿输入文本的起始页做例子,我们就需要同时接受--startPage
与-s
这两种输入,pflag也允许我们这样做:
1 | var inputS = flag.IntP("startPage", "s", -1, "...") |
最后,flag.Parse()
自动进行参数的捕获、解析。如果是没有带-
或--
的参数,则可通过flag.Args()
获取,这类参数的数量为flag.Narg()
。
- bufio
在Selpg的实现中我使用了bufio包来进行输入输出的定向,bufio即buffered I/O,它封装了io.Reader与io.Writer,使用起来还是较为方便的。
读取输入部分:
1 | //从命令行输入 |
定向输出部分:
1 | outputWriter = bufio.NewWriter(os.Stdout) |
- os/exec
“-dXXX”的实现可能是比较难的一部分,这里通过os/exec包来实现,exec允许运行外部命令,它封装了os.StartProcess,故我们可以更容易地重定向输入输出,可通过管道向命令输入内容。
当-d
参数获得了一个打印机地址,就进行如下操作:
1 | //初始化外部命令 |
注意cmd.CombinedOutput()
的作用是运行命令并获得组合在一起的stdout/stderr输出。
简单测试
selpg -s1 -e1
即,从命令行输入,并输出到命令行,打印前72行(default)
selpg -s1 -e1 -l3 input
即,从文件输入,并输出到命令行,打印前三行
selpg -s1 -e input >output 2>error
即,正确输出到文件output,错误输出至文件error(故意写成错误命令)
- 测试换页符,首先建立包含换页符的文件:
接着,测试selpg -s1 -e3 -f input
- 测试输出至打印机lp1
命令正确执行了,只是没有打印机
selpg -s1 -e20 -l20 test.txt | grep -n "Geralt"
测试读取并输出长篇小说的前20页(设置每页长20行)
这样就实现了selpg程序。