selpg开发

来源:互联网 发布:mac图片压缩软件 编辑:程序博客网 时间:2024/06/05 05:38

selpg

golang for selpg(CLI)

开发 Linux 命令行实用程序


1. usage

1.  $ selpg -s=1 -e=1 input_file    该命令将把“input_file”的第 1 页写至标准输出(也就是屏幕),因为这里没有重定向或管道。2.  $ selpg -s=1 -e=1 < input_file    该命令与示例 1 所做的工作相同,但在本例中,selpg 读取标准输入,而标准输入已被 shell/内核重定向为来自“input_file”而不是显式命名的文件名参数。输入的第 1 页被写至屏幕。3.  $ other_command | selpg -s=10 -e=20    “other_command”的标准输出被 shell/内核重定向至 selpg 的标准输入。将第 10 页到第 20 页写至 selpg 的标准输出(屏幕)。4.  $ selpg -s=10 -e=20 input_file >output_file    selpg 将第 10 页到第 20 页写至标准输出;标准输出被 shell/内核重定向至“output_file”。5.  $ selpg -s=10 -e=20 input_file 2>error_file    selpg 将第 10 页到第 20 页写至标准输出(屏幕);所有的错误消息被 shell/内核重定向至“error_file”。请注意:在“2”和“>”之间不能有空格;这是 shell 语法的一部分(请参阅“man bash”或“man sh”)。6.  $ selpg -s=10 -e=20 input_file >output_file 2>error_file    selpg 将第 10 页到第 20 页写至标准输出,标准输出被重定向至“output_file”;selpg 写至标准错误的所有内容都被重定向至“error_file”。当“input_file”很大时可使用这种调用;您不会想坐在那里等着 selpg 完成工作,并且您希望对输出和错误都进行保存。7.  $ selpg -s=10 -e=20 input_file >output_file 2>/dev/null    selpg 将第 10 页到第 20 页写至标准输出,标准输出被重定向至“output_file”;selpg 写至标准错误的所有内容都被重定向至 /dev/null(空设备),这意味着错误消息被丢弃了。设备文件 /dev/null 废弃所有写至它的输出,当从该设备文件读取时,会立即返回 EOF。8.  $ selpg -s=10 -e=20 input_file >/dev/null    selpg 将第 10 页到第 20 页写至标准输出,标准输出被丢弃;错误消息在屏幕出现。这可作为测试 selpg 的用途,此时您也许只想(对一些测试情况)检查错误消息,而不想看到正常输出。9.  $ selpg -s=10 -e=20 input_file | other_command    selpg 的标准输出透明地被 shell/内核重定向,成为“other_command”的标准输入,第 10 页到第 20    页被写至该标准输入。“other_command”的示例可以是 lp,它使输出在系统缺省打印机上打          印。“other_command”的示例也可以 wc,它会显示选定范围的页中包含的行数、字数和字数。“other_command”可以是任何其它能从其标准输入读取的命令。错误消息仍在屏幕显示。10. $ selpg -s=10 -e=20 input_file 2>error_file | other_command    与上面的示例 9 相似,只有一点不同:错误消息被写至“error_file”。    $ selpg -s=10 -e=20 -l=10    定义每一页为10行输出    $ selpg -s=10 -e=20 -f    定义文档为f格式,遇到'\f'为一页的终止符

2. test

./selpg -s=1 -e=1 -l=10 text.txt

./selpg -s=1 -e=1 -l=5 \~/Desktop/hello.cpp >\~/Desktop/text.txt

./selpg2 -s=1 -e=1 -f text.txt

./selpg2 -s=1 -e=1


3. design process

导入所需要的包

import (    "bufio"    "fmt"    "os"    "os/exec"    "strconv"    "strings")

定义结构提体

type selpgArgs struct {    startPage  int    // start page of the article    endPage    int    // end page of the article    inFilename string // name of the file to be read    pageLen    int    /* number of lines in one page, default value is 72,       can be overriden by "-lNumber" on command line */    pageType rune /* type of the article, 'l' for lines-delimited, 'f' for form-feed-delimited       default is 'l'. */    printDest string // destination of result pages}

函数接口


4.代码

func usage();func processArgs(argNums int, args []string, saAddr *selpgArgs);func processInput(saAddr *selpgArgs);
package mainimport (    "bufio"    "fmt"    "os"    "os/exec"    "strconv"    "strings")type selpgArgs struct {    startPage  int    // start page of the article    endPage    int    // end page of the article    inFilename string // name of the file to be read    pageLen    int    /* number of lines in one page, default value is 72,       can be overriden by "-lNumber" on command line */    pageType rune /* type of the article, 'l' for lines-delimited, 'f' for form-feed-delimited       default is 'l'. */    printDest string // destination of result pages}var progname string // name of program, used to display error messagefunc usage() {    fmt.Fprintf(os.Stderr,        "\nUSAGE: %s -s=start_page(number) -e=end_page(number) [ -f | -l=lines_per_page(number) ] [ -ddest ] [ in_filename ]\n", progname)}func processArgs(argNums int, args []string, saAddr *selpgArgs) {    // check if the number of arguments is valid    if argNums < 3 {        fmt.Fprintf(os.Stderr, "%s: not enough arguments\n", progname)        usage()        os.Exit(1)    }    // handle 1st arg - start page    tmpStr := []rune(args[1])    if tmpStr[0] != '-' || tmpStr[1] != 's'||tmpStr[2] != '=' {        fmt.Fprintf(os.Stderr, "%s: 1st arg should be -sstart_page\n", progname)        usage()        os.Exit(2)    }    page, err := strconv.Atoi(string(tmpStr[3:]))    if page < 1 || err != nil {        fmt.Fprintf(os.Stderr, "%s: invalid start page %s\n", progname, string(tmpStr[3:]))        usage()        os.Exit(3)    }    saAddr.startPage = page    // handle 2nd arg -end page    tmpStr = []rune(args[2])    if tmpStr[0] != '-' || tmpStr[1] != 'e' || tmpStr[2] != '=' {        fmt.Fprintf(os.Stderr, "%s: 2nd arg should be -eend_page\n", progname)        usage()        os.Exit(4)    }    page, err = strconv.Atoi(string(tmpStr[3:]))    if page < 1 || page < saAddr.startPage || err != nil {        fmt.Fprintf(os.Stderr, "%s: invalid start page %s\n", progname, string(tmpStr[3:]))        usage()        os.Exit(5)    }    saAddr.endPage = page    // handle optional args    argIndex := 3    for argIndex < argNums && []rune(args[argIndex])[0] == '-' {        tmpStr = []rune(args[argIndex])        switch tmpStr[1] {        case 'l':      if tmpStr[2]!='=' {        usage()        os.Exit(13)      }            lineNum, err := strconv.Atoi(string(tmpStr[3:]))            if lineNum < 1 || err != nil {                fmt.Fprintf(os.Stderr, "%s: invalid page length %s\n", progname, string(tmpStr[2:]))                usage()                os.Exit(6)            }            saAddr.pageLen = lineNum            argIndex++        case 'f':            if strings.Compare(string(tmpStr), "-f") != 0 {                fmt.Fprintf(os.Stderr, "%s: option should be \"-f\"\n", progname)                usage()                os.Exit(7)            }            saAddr.pageType = 'f'            argIndex++        case 'd':            if len(tmpStr[2:]) < 1 {                fmt.Fprintf(os.Stderr, "%s: -d option requires a printer destination\n", progname)                usage()                os.Exit(8)            }            saAddr.printDest = string(tmpStr[2:])            argIndex++        default:            fmt.Fprintf(os.Stderr, "%s: unknown option %s\n", progname, string(tmpStr))            usage()            os.Exit(9)        } // end switch    } // end while    // there is one more argument    if argIndex <= argNums-1 {        saAddr.inFilename = args[argIndex]        // check if file exists        f, err := os.Open(saAddr.inFilename)        if err != nil {            fmt.Fprintf(os.Stderr, "%s: input file \"%s\" does not exist\n", progname, saAddr.inFilename)            os.Exit(10)        }        f.Close()    }}func processInput(saAddr *selpgArgs) {    // set the input source    fin := os.Stdin    var err error    if saAddr.inFilename != "" {        fin, err = os.Open(saAddr.inFilename)        if err != nil {            fmt.Fprintf(os.Stderr, "%s: could not open input file \"%s\"\n", progname, saAddr.inFilename)            os.Exit(11)        }    }    // set the ouput destination    fout := os.Stdout    var cmd *exec.Cmd    if saAddr.printDest != "" {        tmpStr := fmt.Sprintf("./%s", saAddr.printDest)        cmd = exec.Command("sh", "-c", tmpStr)        if err != nil {            fmt.Fprintf(os.Stderr, "%s: could not open pipe to \"%s\"\n", progname, tmpStr)            os.Exit(12)        }    }    // dealing with the page type    var line string    pageCnt := 1    inputReader := bufio.NewReader(fin)    rst := ""    if saAddr.pageType == 'l' {        lineCnt := 0        for true {            line, err = inputReader.ReadString('\n')            if err != nil { // error or EOF                break            }            lineCnt++            if lineCnt > saAddr.pageLen {                pageCnt++                lineCnt = 1            }            if pageCnt >= saAddr.startPage && pageCnt <= saAddr.endPage {                if saAddr.printDest == "" {                    fmt.Fprintf(fout, "%s", line)                } else {                    rst += line                }            }        }    } else {        for true {            c, _, erro := inputReader.ReadRune()            if erro != nil { // error or EOF                break            }            if c == '\f' {                pageCnt++            }            if pageCnt >= saAddr.startPage && pageCnt <= saAddr.endPage {                if saAddr.printDest == "" {                    fmt.Fprintf(fout, "%c", c)                } else {                    rst += string(c)                }            }        }    }    if saAddr.printDest != "" {        cmd.Stdin = strings.NewReader(rst)        cmd.Stdout = os.Stdout        err = cmd.Run()        if err != nil {            fmt.Println("print error!")        }    }    if pageCnt < saAddr.startPage {        fmt.Fprintf(os.Stderr, "%s: start_page (%d) greater than total pages (%d), no output written\n", progname, saAddr.startPage, pageCnt)    } else {        if pageCnt < saAddr.endPage {            fmt.Fprintf(os.Stderr, "%s: end_page (%d) greater than total pages (%d), less output than expected\n", progname, saAddr.endPage, pageCnt)        }    }    fin.Close()    fout.Close()    fmt.Fprintf(os.Stderr, "%s: done\n", progname)}func main() {    sa := new(selpgArgs)    progname = os.Args[0] // get the name of the program    // initial selpg's arguments to default values    sa.startPage = -1    sa.endPage = -1    sa.inFilename = ""    sa.pageLen = 20    sa.pageType = 'l'    sa.printDest = ""    processArgs(len(os.Args), os.Args, sa)    processInput(sa)}
原创粉丝点击