Selpg—Golang

源代码
开始
  • 了解Pflag包的作用
  • 懂得利用Go语言实现文件读入写出
了解Pflag包的作用
安装pflag
  • 在终端输入以下命令
go get github.com/spf13/pflag
参数处理
  • 输入以下代码,并保存为test.go
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) {
	//get reader
	var reader *bufio.Reader
	reader = getReader(args)

	//get writer
	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)
		}
	}
}
按行读并输出到屏幕
  • 循环读至s页,从s页开始到e页输出读入的内容
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()
			}
		}
	}
}
按页读并输出到屏幕
  • 循环读至s页,从s页开始到e页输出读入的内容
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

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值