【服务计算】使用 golang 开发CLI 命令行实用程序 —— selpg.go

目录

  • 概述
  • 关于原版selpg
    1.功能
    2.如何使用
    3.selpg.c
  • selpg.go
    1.selpg_args struct
    2.global variable
    3.main
    4.process_args
    5.process_input
  • 代码地址
  • 测试结果

概述

CLI(Command Line Interface)实用程序是Linux下应用开发的基础。在开发领域,CLI在编程、调试、运维、管理中提供了图形化程序不可替代的灵活性与效率。

本文简单叙述了如何使用Go语言开发 Linux 命令行实用程序,具体来讲,就是用go语言实现开发 Linux 命令行实用程序一文中已经用c语言实现了的selpg程序。

据说很多同学看完老师给的资料后还是一头雾水(比如我),希望本文能让学弟学妹们大概清楚这次作业到底要做什么:P


关于原版selpg

1.功能

selpg 允许用户指定从输入文本抽取的页的范围,这些输入文本可以来自文件或另一个进程。例如,如果输入含有 100 页,则用户可指定只打印第 35 至 65 页。

2.如何使用

原文给出了一些可使用的 selpg 命令字符串示例,这些命令也可以用来测试我们的go版本的selpg(举三个例子):

$ selpg -s1 -e1 input_file

该命令将把“input_file”的第 1 页写至标准输出(也就是屏幕)

$ other_command | selpg -s10 -e20

other_command”的标准输出被 shell/内核重定向至 selpg 的标准输入。将第 10 页到第 20 页写至 selpg 的标准输出(屏幕)。

selpg -s10 -e20 input_file >output_file 2>error_file

selpg 将第 10 页到第 20 页写至标准输出,标准输出被重定向至“output_file”;selpg 写至标准错误的所有内容都被重定向至“error_file”。

也就是说,我们可以通过一句命令行来使这个程序跑起来(在此之前,我们需要安装这个程序,并准备好可能会用到的输入文件(如test.txt)和输出文件(如result.txt))。这句命令的格式如下,其中,-s表示开始打印的页码,-e表示结束打印的页码,这两个必须写上;而-l表示按固定行数打印文件,-f表示按照换页符来打印,默认按行;-d则是打印的目的地,默认为屏幕。

selpg -s startPage -e endPage [-l linePerPage | -f ][-d dest] filename

3.selpg.c

是时候详细研究源代码了。具体参考原文代码注释部分。

源码首先定义了一个类型,即selpg_args 结构

struct selpg_args
{
	int start_page;
	int end_page;
	char in_filename[BUFSIZ];
	int page_len; /* default value, can be overriden by "-l number" on command line */
	int page_type; /* 'l' for lines-delimited, 'f' for form-feed-delimited */
					/* default is 'l' */
	char print_dest[BUFSIZ];
};

事实上,这个结构存储了用户从命令行输入的一些信息,比如输入:

$ selpg -s1 -e1 test.txt

selpg_args里就将start_page和end_page设为1,将in_filename设为test.txt,其他参数均为默认值。

接着来看main函数,这个函数很简单,首先声明一个名为sa的selpg_args,然后初始化selpg_args里的各个参数,接着调用其他两个函数。

process_args函数主要是分析用户输入的命令,进行错误检查,并将各种信息存储在sa中。别被源码长度吓到了,在go中,我们可以使用pflag来帮助我们分析命令行,我们只需要用pflag绑定sa的各个参数,命令行中的信息就会自动存入sa,而不用我们自己一个个去操作。当然,我们仍然需要检查数据的合法性。

process_input函数,首先设置输入源,就是选择从哪里进行读取,然后设置输出源,就是选择打印到哪里,接下来就是真正的打印工作了。这个函数是最难的部分,特别是文件操作。

usage函数用来打印帮助信息。


selpg.go

1.selpg_args struct

可以直接翻译,很简单。

2.global variable

声明用来保存程序名字的全局变量,显示错误信息的时候会用到它。

3.main

由于我们使用pflag绑定了sa的各个变量,我们可以省略在main初始化的部分,其他基本一致。

4.process_args

这里推荐一篇文章:golang flag包使用笔记,是老师给的博客的个人笔记,小白友好型文章。

首先将flag绑定到sa的各个变量上,如:

flag.IntVarP(&sa.start_page,"start",  "s", -1, "start page(>1)")

第一个参数为变量;第二个参数为命令行参数名;第三个参数为该参数的短名;第四个参数为该参数没有在命令行出现时的默认值;第五个参数是help的帮助信息。

接着调用flag.Parse()解析命令行参数到定义的flag。

然后就是各个变量的合法性检查了。

5.process_input

与selpg.c一样,我们先选择从哪里读取和在哪儿打印,接着按照page_type进行打印。

参考资料:
go如何读文件:12.2 文件读写
用cmd进行重定向(等下解释):golang中os/exec包用法

在选择往哪儿打印时,如果用户指定了打印地点,我们就使用cmd来进行重定向,也就是说,selpg程序读取了文件,并将读取的内容放到了输出流中,此时,我们使用cmd运行另外一个程序,比如执行cat,将输出流中的内容打印到指定的地址。

至于如何打印,可以自行google~


代码地址

我的github


测试结果

本学渣要累死了,明天更。。


来了来了。。(为了便于测试,sa.page_len设为7)
1.selpg -s1 -e1 input_file
【服务计算】使用 golang 开发CLI 命令行实用程序 —— selpg.go_第1张图片
2.selpg -s1 -e1 < input_file
【服务计算】使用 golang 开发CLI 命令行实用程序 —— selpg.go_第2张图片
3.other_command | selpg -s10 -e20
【服务计算】使用 golang 开发CLI 命令行实用程序 —— selpg.go_第3张图片
4.selpg -s10 -e20 input_file >output_file
【服务计算】使用 golang 开发CLI 命令行实用程序 —— selpg.go_第4张图片
【服务计算】使用 golang 开发CLI 命令行实用程序 —— selpg.go_第5张图片
5.selpg -s10 -e20 input_file 2>error_file
【服务计算】使用 golang 开发CLI 命令行实用程序 —— selpg.go_第6张图片
【服务计算】使用 golang 开发CLI 命令行实用程序 —— selpg.go_第7张图片
【服务计算】使用 golang 开发CLI 命令行实用程序 —— selpg.go_第8张图片
6.selpg -s10 -e20 input_file >output_file 2>error_file
【服务计算】使用 golang 开发CLI 命令行实用程序 —— selpg.go_第9张图片

【服务计算】使用 golang 开发CLI 命令行实用程序 —— selpg.go_第10张图片
7.selpg -s10 -e20 input_file >output_file 2>/dev/null
【服务计算】使用 golang 开发CLI 命令行实用程序 —— selpg.go_第11张图片
【服务计算】使用 golang 开发CLI 命令行实用程序 —— selpg.go_第12张图片
8.selpg -s10 -e20 input_file >/dev/null
【服务计算】使用 golang 开发CLI 命令行实用程序 —— selpg.go_第13张图片
9.selpg -s10 -e20 input_file | other_command
9
10.selpg -s10 -e20 input_file 2>error_file | other_command
【服务计算】使用 golang 开发CLI 命令行实用程序 —— selpg.go_第14张图片
11.selpg -s10 -e20 -l66 input_file
11
12.selpg -s10 -e20 -f input_file
12
13.selpg -s10 -e20 -dlp1 input_file
【服务计算】使用 golang 开发CLI 命令行实用程序 —— selpg.go_第15张图片

你可能感兴趣的:(服务计算)