使用 golang 開發selpg

2021-09-27 09:34:59 字數 4817 閱讀 4975

程式設計

開發linux命令列實用程式

cli 命令列實用程式開發基礎

selpg從標準輸入或從作為命令列引數給出的檔名讀取文字輸入。它允許使用者指定來自該輸入並隨後將被輸出的頁面範圍。

$ command input_file
$ command
$ command

< input_file

$ other_command |

command

$ command
$ command

> output_file

$ command

| other_command

selpg 要求使用者用兩個命令列引數「-snumber」(例如,「-s10」表示從第 10 頁開始)和「-enumber」(例如,「-e20」表示在第 20 頁結束)指定要抽取的頁面範圍的起始頁和結束頁。selpg 對所給的頁號進行合理性檢查;換句話說,它會檢查兩個數字是否為有效的正整數以及結束頁是否不小於起始頁。這兩個選項,「-snumber」和「-enumber」是強制性的,而且必須是命令列上在命令名 selpg 之後的頭兩個引數:

selpg 可以處理兩種輸入文字:

型別 1:該類文字的頁行數固定(每頁 72 行)。這是預設型別,因此不必給出選項進行說明。該預設值可以用「-lnumber」選項覆蓋,如下所示:

$ selpg -s10 -e20 -l66
這表明頁有固定長度,每頁為 66 行。

型別 2:該型別文字的頁由 ascii 換頁字元(十進位制數值為 12,在 c 中用「\f」表示)定界。型別 2 格式由「-f」選項表示,如下所示:

$ selpg -s10 -e20 -f ...
該命令告訴 selpg 在輸入中尋找換頁符,並將其作為頁定界符處理。

注:「-lnumber」和「-f」選項是互斥的。

$ lp -ddestination
的管道以便輸出,並寫至該管道而不是標準輸出:

selpg -s10 -e20 -dlp1
該命令將選定的頁作為列印作業傳送至 lp1 列印目的地。

引數結構體

設計乙個結構體記錄存放的引數。包括開始頁、結束頁、輸入檔案的名字、輸出、一頁的長度、分頁方式

type selpg_args struct

設定全域性變數記錄讀取到的引數、程式名和引數個數

var sa selpg_args   

var progname string

var argcount int

讀取並處理引數。

使用os.args(參考資料)獲取使用者輸入的引數,得到乙個包含引數的陣列,陣列中的每個元素是string型別的。

引數處理可以使用pflag包來解析命令的引數。參考資料

要import pflag包,要先在本地安裝spf13/pflag

go get github.com/spf13/pflag
然後可以通過下面的**進行引數值的繫結,通過 pflag.parse()方法讓pflag 對標識和引數進行解析。之後就可以直接使用繫結的值。

pflag.

intvarp

(&sa.start_page,

"start"

,"s",0

,"start page of file"

)pflag.

intvarp

(&sa.end_page,

"end"

,"e",0

,"end page of file"

)pflag.

intvarp

(&sa.page_len,

"linenum"

,"l",20

,"lines in one page"

)pflag.

strin**arp

(&sa.page_type,

"printdes"

,"f"

,"l"

,"flag splits page"

)pflag.

strin**arp

(&sa.dest,

"destination"

,"d",""

,"name of printer"

)pflag.

parse

()

提示資訊,如果給出的引數不正確或者需要檢視幫助 -help,那麼會給出這裡指定的字串

pflag.usage = show_tips
通過pflag.narg()可以知道是否有要進行操作的檔案。如果是pflag解析不了的型別引數。我們稱這種引數為non-flag引數,flag解析遇到non-flag引數就停止了。pflag提供了arg(i),args()來獲取non-flag引數,narg()來獲取non-flag的個數。所以可以使用pflag.arg(0)來獲取輸入的檔案路徑

另外,如果手動判斷每個引數,則需要判斷引數個數、引數格式是否符合要求。不符合要求則輸出錯誤資訊,終止程式;符合要求則賦給引數結構體的每個變數中。

if

len(args)

<

3

if args[1]

[0]!=

'-'|| args[1]

[1]!=

's'

如果是,則從陣列中提取出引數

sp,

_:= strconv.

atoi

(args[1]

[2:]

)if sp <

1 sa.start_page = sp

if args[2]

[0]!=

'-'|| args[2]

[1]!=

'e'ep,

_:= strconv.

atoi

(args[2]

[2:]

)if ep <

1|| ep < sp

sa.end_page = ep

如果引數個數大於三,需要獲取其他引數資訊,可能是"-l", 「-f」, 「-d」。需要確認是以"-"開頭才能進行引數判斷

迴圈讀取

for

switch args[argindex][1

] sa.page_len = pl

argindex++

-f

-f引數後面不跟數字,所以判斷-f引數的長度來判斷是否合法

case

'f':

iflen

(args[argindex]

)>

2 sa.page_type =

'f' argindex++

-d

根據說明,selpg不檢查destination目的地,但是要確保-d後面跟著目的地,即引數長度不應該只有2

if

len(args[argindex])==

2 sa.destination = args[argindex][2

:]argindex++

不合法引數

如果不是以上的任何一種情況,需要報錯處理

default

: fmt.

fprintf

(os.stderr,

"%s: unknown option"

, progname)

usage()

os.exit(1

)

if argindex <= argcount-

1

從標準輸入或檔案中獲取輸入然後輸出到標準輸出或檔案中
var cmd *exec.cmd

var cmd_in io.writecloser

var cmd_out io.readcloser

if sa.destination !=

""

使用os/exec包,可以執行外部命令,將輸出的資料作為外部命令的輸入。使用exec.command設定要執行的外部命令,cmd.stdinpipe()返回連線到command標準輸入的管道pipe,cmd.start()使某個命令開始執行,但是並不等到他執行結束。

line,

_, err := fin.

readline()

if err != io.eof && err !=

nilif err == io.eof

if page_count >= sa.start_page && page_count <= sa.end_page

else

} line_count++

if line_count > sa.page_len
if

string

(line)

=="\f"

golang開發 channel使用

channel主要是用於多個goroutine之間通訊 channel是引用型別,需要實用make來建立channel,如下 make chan type,buffer chan type 通道的型別 buffer 是可選引數,代表通道緩衝區的大小 省略則代表無緩衝 向channel裡面寫入資料使用...

golang開發 channel使用

channel主要是用於多個goroutine之間通訊 channel是引用型別,需要實用make來建立channel,如下 make chan type,buffer chan type 通道的型別 buffer 是可選引數,代表通道緩衝區的大小 省略則代表無緩衝 向channel裡面寫入資料使用...

golang開發中channel使用

channel 通道 是golang的一種重要特性,正是因為channel的存在才使得golang不同於其它語言。channel使得併發程式設計變得簡單容易有趣。channel的概念和語法 乙個channel可以理解為乙個先進先出的訊息佇列。channel用來在協程 goroutine 之前傳遞資料...