selPage命令简介

该命令是以标准的linux命令行程序为参照,采用golang进行编写的。
作用是可以从某个输入文档中截取指定页数的文本到标准输出或者重定向文件。

具体用法

该指令支持-s,-e,-l,-f 标准参数以及之后的可选参数。

  1. -s ,指定截取文本的起始页数,该页也包含在内,写法为-sNum,其中Num为正整数,默认为1;
  2. -e ,指定截取文本的末尾页数,用法和-s类似,默认值为1000;
  3. -l ,指定了每一页的行数,程序将会按照指定的行数来确定每一页的结尾,该指令和-f指令不可同时出现;
  4. -f ,单独使用,指定了程序按照换页符 ‘\f’ 来界定每一页的结尾;
    如果-l和-f均未指定的话,将会采用-l的默认值72来实现;
  5. 必选的标准参数inFile,紧跟在所有标准参数之后,用于指明程序的输入来源,应该为某个文件的路径;
  6. 非必选的重定向指令,linux命令行程序中所有的重定向指令都可以加在该指令之后,从而使该指令更加灵活。

使用示例

go selPage.go -s2 -e5 -l60 ./test.file
go selvage.go -s2 -e6 ./test.file >./test2.file
go selvage.go -s2 -e6 -f ./test.file 1&>2
等等。

使用的组件:pflag

导入方式 在将该地址上的包通过 go get 指令下载到本地后,将这行代码添加到package下面:import flag "github.com/spf13/pflag"

pflagflag

以下是代码中使用到了该包内容的相关部分

flag.typeP

func wordSepNormalizeFunc(f *flag.FlagSet, name string) flag.NormalizedName {
	from := []string{"-", "_"}
	to := "."
	for _, sep := range from {
		name = strings.Replace(name, sep, to, -1)
	}
	return flag.NormalizedName(name)
}
flag.CommandLine.SetNormalizeFunc(wordSepNormalizeFunc)
s := flag.IntP("startPage", "s", 1, "this decides the start page, default 1 ")
e := flag.IntP("endPage", "e", 1000, "this decides the end page, default 1000 ")
l := flag.IntP("pageLines", "l", 72, "this decides the lines one page, default 72 ")
flag.StringP("usef", "f", "", "this decides use the \\f, no argument")

flag.Parse()
wordSepNormalizeFunctypePflag.Parse

flag.Arg

flag.Args()flag.Arg(num int)flag.NFlag() / flag.NArg()flag.LookUp(name string).changed
if *s > *e {
	ErrReport("startPage must smaller than or equal with endPage")
}
isL, isF := flag.Lookup("pageLines").Changed, flag.Lookup("usef").Changed
if isL && isF {
	ErrReport("l and f argus at the same time")
}
ErrReport
func ErrReport(err ...string) {
	var strs = err
	for _, str := range strs {
		_, _ = fmt.Fprintln(os.Stderr, str)
	}
	os.Exit(2)
}
重定向处理
>fileName1/2>&fileName1/2&>1/2
var outFile string

for n, arg := range flag.Args() {
	if n == 0 {
		continue
	}
	if arg[0:1] == ">" {
		outFile = arg[1:]
		f, err := os.OpenFile(outFile, os.O_RDWR | os.O_APPEND, 666)
		if err != nil {
			panic(err)
		}
		os.Stdout = f
	}else if arg[1:3] == "&>" {
		outFile = arg[3:]
		f, err := os.OpenFile(outFile, os.O_RDWR | os.O_APPEND, 666)
		if err != nil {
			panic(err)
		}
		if arg[0:1] == "1" {
			os.Stdout = f
		}else {
			os.Stderr = f
		}
	}else if arg[1:3] == ">&" {
		if arg[0:1] == "1" {
			os.Stdout = os.Stderr
		}else {
			os.Stderr = os.Stdout
		}
	}else {
		ErrReport("无法解析该命令:", arg)
	}
}
os.Openos.OpenFile
文件输入
readBytes('\n')readBytes('\f')
func readByLine(f *os.File, s, e, l int) {
	countL, countP := 0, 0
	reader := bufio.NewReader(f)
	for ;countP < s-1; {
		countL = 0
		for {
			_, _ = reader.ReadBytes('\n')
			countL++;
			if countL >= l {
				countP++
				break
			}
		}
	}
	for ; countP < e; {
		countL = 0;
		for {
			bytes, err := reader.ReadBytes('\n')
			if err != nil {
				panic(err)
			}
			lines += string(bytes)
			_, _ = fmt.Fprintf(os.Stderr, "读入 %d 个字节\n", len(bytes))
			countL++;
			if countL >= l {
				countP++
				break
			}
		}
	}
}
func readByF(f *os.File, s, e int) {
	countP := 0
	reader := bufio.NewReader(f)
	for ;countP < s-1; {
		_, _ = reader.ReadBytes('\f')
	}
	for ; countP < e; {
		bytes, err := reader.ReadBytes('\f')
		if err != nil {
			panic(err)
		}
		lines += string(bytes)
		_, _ = fmt.Fprintf(os.stderr, "读入 %d 个字节", len(bytes))
	}
}

至于内容输出,则是简单地将保存的string类型数据放置到标准输出中,因为前面已经进行了输出的重定向,因此这里也就会被输出到相应的地方去。