源代码
开始
了解Pflag包的作用 懂得利用Go语言实现文件读入写出
了解Pflag包的作用
安装pflag
go get github.com/spf13/pflag
参数处理
package main
import (
"fmt"
flag "github.com/spf13/pflag"
)
func main ( ) {
var s int
flag. IntVarP ( & s, "start" , "s" , 0 , "startPage" )
flag. Parse ( )
fmt. Printf ( "%d\n" , s)
}
$ go build test.go
$ ./test
0
$ ./test -s10
10
$ ./test -s20
20
$ ./test --start=30
30
结合终端输出的结果,分析以下test.go代码。
flag.IntVarP定义命令行参数 &s——将命令行参数的值绑定到s变量上 “start”——可以通过- -start=30为参数赋值 “s“——可以通过-s10为参数赋值 最后要通过flag.Parse解析
开始实现Selpg
流程
导入的包
import (
"bufio"
"fmt"
"io"
"os"
"os/exec"
flag "github.com/spf13/pflag"
)
保存命令行参数信息的结构体
type Args struct {
s int
e int
l int
f bool
d string
inputFile string
}
函数介绍
func getArgs(args *Args) :定义命令行参数 func checkArgs(args *Args): 检查参数的合法性 func getReader(args *Args) *bufio.Reader:获取bufio.Reader对象 func execution(args *Args):执行文件读入写出 func readByL(args *Args, reader *bufio.Reader, writer *bufio.Writer):按行读入,并输出到标准输出 func readByF(args *Args, reader *bufio.Reader, writer *bufio.Writer) :按页读入,并输出到标准输出 func readByLWithD(args *Args, reader *bufio.Reader, writer io.WriteCloser) :按行读入,并由管道输出到"-dXXX" func readByFWithD(args *Args, reader *bufio.Reader, writer io.WriteCloser) :按页读入,并由管道输出到"-dXXX"
定义命令行参数
func getArgs ( args * Args) {
flag. IntVarP ( & args. s, "start" , "s" , 0 , "start" )
flag. IntVarP ( & args. e, "end" , "e" , 0 , "end" )
flag. IntVarP ( & args. l, "line" , "l" , - 1 , "line" )
flag. BoolVarP ( & args. f, "final" , "f" , false , "final" )
flag. StringVarP ( & args. d, "inputFile" , "d" , "" , "input file" )
flag. Parse ( )
otherArgs := flag. Args ( )
if len ( otherArgs) > 0 {
args. inputFile = otherArgs[ 0 ]
} else {
args. inputFile = ""
}
}
检查参数合法性
若-s和-e没有赋值或-s的值比-e大,则报错。-f和-l只能有一个。
func checkArgs ( args * Args) {
if args. s == 0 || args. e == 0 {
os. Stderr. Write ( [ ] byte ( "Please input -s and -e\n" ) )
os. Exit ( 0 )
}
if args. s > args. e {
os. Stderr. Write ( [ ] byte ( "Invalid input about -s and -e\n" ) )
os. Exit ( 0 )
}
if args. f && args. l != - 1 {
os. Stderr. Write ( [ ] byte ( "Please choose either -f or -l\n" ) )
os. Exit ( 0 )
}
}
获取bufio.Reader对象
inputFile如果为空,selpg则读标准输入;否则读指定的文件
func getReader ( args * Args) * bufio. Reader {
var reader * bufio. Reader
if args. inputFile == "" {
reader = bufio. NewReader ( os. Stdin)
} else {
file, err := os. Open ( "./" + args. inputFile)
if err != nil {
os. Stderr. Write ( [ ] byte ( "File does not exist\n" ) )
os. Exit ( 1 )
}
reader = bufio. NewReader ( file)
}
return reader
}
执行命令
首先获取bufio.Reader对象,然后根据-d决定writer是bufio.writer对象还是io.WriteCloser,最后根据-f和-l决定是按行读入还是按页读入
func execution ( args * Args) {
var reader * bufio. Reader
reader = getReader ( args)
if args. d == "" {
writer := bufio. NewWriter ( os. Stdout)
if args. f {
readByF ( args, reader, writer)
} else {
readByL ( args, reader, writer)
}
} else {
cmd := exec. Command ( "./" + args. d)
writer, err := cmd. StdinPipe ( )
if err != nil {
fmt. Println ( "Error" , err)
os. Exit ( 1 )
}
if err := cmd. Start ( ) ; err != nil {
fmt. Println ( "Error" , err)
os. Exit ( 1 )
}
if args. f {
readByFWithD ( args, reader, writer)
} else {
readByLWithD ( args, reader, writer)
}
writer. Close ( )
if err := cmd. Wait ( ) ; err != nil {
fmt. Println ( "Error" )
os. Exit ( 1 )
}
}
}
按行读并输出到屏幕
func readByL ( args * Args, reader * bufio. Reader, writer * bufio. Writer) {
for pageCount := 1 ; pageCount <= args. e; pageCount++ {
if pageCount < args. s {
for lineCount := 0 ; lineCount < args. l; lineCount++ {
reader. ReadBytes ( '\n' )
}
} else {
for lineCount := 0 ; lineCount < args. l; lineCount++ {
line, err := reader. ReadBytes ( '\n' )
if err != nil {
if err == io. EOF {
writer. WriteByte ( '\n' )
writer. Flush ( )
break
}
os. Stderr. Write ( [ ] byte ( "Read failed\n" ) )
os. Exit ( 1 )
}
writer. Write ( line)
writer. Flush ( )
}
}
}
}
按页读并输出到屏幕
func readByF ( args * Args, reader * bufio. Reader, writer * bufio. Writer) {
for pageCount := 1 ; pageCount <= args. e; pageCount++ {
for {
char, err := reader. ReadByte ( )
if char == '\f' {
break
}
if err != nil {
if err == io. EOF {
writer. WriteByte ( '\n' )
writer. Flush ( )
break
}
os. Stderr. Write ( [ ] byte ( "Read failed\n" ) )
os. Exit ( 1 )
}
if pageCount >= args. s {
writer. WriteByte ( char)
writer. Flush ( )
}
}
}
}
按行读并由管道输送至命令“-dXXX”
func readByLWithD ( args * Args, reader * bufio. Reader, writer io. WriteCloser) {
for pageCount := 1 ; pageCount <= args. e; pageCount++ {
if pageCount < args. s {
for lineCount := 0 ; lineCount < args. l; lineCount++ {
reader. ReadBytes ( '\n' )
}
} else {
for lineCount := 0 ; lineCount < args. l; lineCount++ {
line, err := reader. ReadBytes ( '\n' )
if err != nil {
if err == io. EOF {
break
}
os. Stderr. Write ( [ ] byte ( "Read failed\n" ) )
os. Exit ( 1 )
}
writer. Write ( line)
}
}
}
}
按页读并由管道输送至命令”-dXXX“
func readByFWithD ( args * Args, reader * bufio. Reader, writer io. WriteCloser) {
for pageCount := 1 ; pageCount <= args. e; pageCount++ {
for {
char, err := reader. ReadByte ( )
if char == '\f' {
break
}
if err != nil {
if err == io. EOF {
break
}
os. Stderr. Write ( [ ] byte ( "Read failed\n" ) )
os. Exit ( 1 )
}
if pageCount >= args. s {
writer. Write ( [ ] byte { char} )
}
}
}
}
测试结果
当前工作目录下的文件 testD.Go源码
package main
import (
"bufio"
"io"
"os"
)
func main ( ) {
reader := bufio. NewReader ( os. Stdin)
file, err := os. OpenFile ( "./testD.txt" , os. O_RDWR| os. O_CREATE, 0666 )
if err != nil {
os. Stderr. WriteString ( "Open Failed" )
}
writer := bufio. NewWriter ( file)
for {
line, err := reader. ReadBytes ( '\n' )
if err != nil {
if err == io. EOF {
break
}
os. Stderr. Write ( [ ] byte ( "Read error\n" ) )
os. Exit ( 1 )
}
writer. Write ( line)
writer. Flush ( )
}
}
$ ./selpg -s1 -e1 vocabulary.md
$ env | ./selpg -s1 -e1 -l2
$ ./selpg -s1 -e1 vocabulary.md > 1.txt
$ ./selpg -s1 -e1 -dtestD vocabulary.md