先上测试结果:
sa.page_len = 3;
将一页长度定义为3行
测试文件test.txt如下:
命令一:go run selpg.go -s1 -e1 test.txt
命令二:go run selpg.go -s1 -e1 < test.txt
命令三:java -version | go run selpg.go -s1 -e1
命令四:go run selpg.go -s1 -e2 test.txt >test4.txt
命令五:go run selpg.go -s1 -e2 test.txt 2>error5.txt
shell输出
error5.txt文件
命令六:go run selpg.go -s1 -e2 test.txt >test6.txt 2>error6.txt
输出到detext6.txt的文件
错误信息
命令七:go run selpg.go -s1 -e2 test.txt >test7.txt 2>/dev/null
保留输出信息,舍弃错误信息
命令八:go run selpg.go -s1 -e2 test.txt > /dev/null
输出信息舍弃
命令九:go run selpg.go -s1 -e2 test.txt | cat
selpg程序的标准输出定位到cat的标准输入。
命令十:go run selpg.go -s1 -e2 test.txt 2>error10.txt | cat
输出结果同命令九
命令十一:go run selpg.go -s1 -e2 -l66 test.txt
一页的长度改变了,所以输出全部
命令十二:go run selpg.go -s1 -e2 -f test.txt
命令十三:go run selpg.go -s1 -e2 -dlp1 test.txt
命令十四:go run selpg.go -s1 -e2 test.txt > test14.txt 2>error14 &
根据教程里给的c语言文件转换为go语言文件。 由于这两种不同的语言的语法也是不一样的,并不能直接转换。
简略给出设计的步骤:
1.首先要导入所需要的包
import (
"fmt"
"os"
"strings"
"strconv"
"bufio"
"io"
"os/exec"
)
2.定义结构提体
type selpg_args struct {
start_page int
end_page int
in_filename string
page_len int
page_type int
print_dest string
}
3.函数接口,语法转换:两者相似的地方,也有很多相异。整体来说转换过程不算困难。 方法接口转换:两者包和库有多个相似功能,但转换过程比较困难,原因在于未能熟练使用语言的包。经过在百度和官方文档 中的查阅,最终得以解决。
代码具体:
package main
import (
"fmt"
"os"
"strings"
"strconv"
"bufio"
"io"
"os/exec"
)
type selpg_args struct {
start_page int
end_page int
in_filename string
page_len int
page_type int
print_dest string
}
type sp_args selpg_args
var progname string
const DEBUG bool = true
const INT_MAX int = (1 << 31) - 1
func main() {
for i, a := range os.Args[1:] {
fmt.Printf("Argument %d is %s\n", i+1, a)
}
var sa selpg_args
progname = os.Args[0]
sa.start_page = -1
sa.end_page = -1
sa.in_filename = ""
sa.page_len = 72;
sa.page_type = 'l'
sa.print_dest = ""
process_args(len(os.Args), os.Args, &sa)
process_input(sa)
}
func process_args(ac int, av []string, psa *selpg_args) {
var s1 string /* temp str */
var s2 string /* temp str */
var argno int /* arg # currently being processed */
/* arg at index 0 is the command name itself (selpg),
first actual arg is at index 1,
last arg is at index (ac - 1) */
var i int
/* check the command-line arguments for validity */
if (ac < 3) {
fmt.Fprintf(os.Stderr, "%s: not enough arguments\n", progname)
usage();
os.Exit(1)
}
if (DEBUG) {
fmt.Fprintf(os.Stderr, "DEBUG: before handling 1st arg\n")
}
s1 = av[1]
var substr1 = s1[0:2]
if (!strings.EqualFold(substr1, "-s")) {
fmt.Fprintf(os.Stderr, "%s: 1st arg should be -sstart_page\n", progname)
usage();
os.Exit(2)
}
i, _ = strconv.Atoi(s1[2:len(s1)])
if ( i < 1 || i > (INT_MAX - 1) ) {
fmt.Fprintf(os.Stderr, "%s: invalid start page %s\n", progname, s1[2:len(s1)])
usage()
os.Exit(3)
}
psa.start_page = i
if (DEBUG) {
fmt.Fprintf(os.Stderr, "DEBUG: before handling 2nd arg\n")
}
s1 = av[2]
substr1 = s1[0:2]
if (!strings.EqualFold(substr1, "-e")) {
fmt.Fprintf(os.Stderr, "%s: 2nd arg should be -eend_page\n", progname)
usage();
os.Exit(4)
}
i, _ = strconv.Atoi(s1[2:len(s1)])
if ( (i < 1) || (i > (INT_MAX - 1)) || (i < psa.start_page) ) {
fmt.Fprintf(os.Stderr, "%s: invalid end page %s\n", progname, s1[2:len(s1)])
usage();
os.Exit(5)
}
psa.end_page = i
if (DEBUG) {
fmt.Fprintf(os.Stderr, "DEBUG: before while loop for opt args\n")
}
argno = 3;
for (argno <= (ac - 1) && av[argno][0] == '-') {
s1 = av[argno]
switch(s1[1]) {
case 'l':
s2 = s1[2:len(s1)]
i, _ = strconv.Atoi(s2)
if ( i < 1 || i > (INT_MAX - 1) ) {
fmt.Fprintf(os.Stderr, "%s: invalid page length %s\n", progname, s2)
usage()
os.Exit(6)
}
psa.page_len = i
argno++
continue
break /* break after continue not reqd, defensive prog. */
case 'f':
/* check if just "-f" or something more */
if (!strings.EqualFold(s1, "-f")) {
fmt.Fprintf(os.Stderr, "%s: option should be \"-f\"\n", progname)
usage()
os.Exit(7)
}
psa.page_type = 'f'
argno++
continue
break
case 'd':
s2 = s1[2:len(s1)]
if (len(s2) < 1) {
fmt.Fprintf(os.Stderr,
"%s: -d option requires a printer destination\n", progname)
usage()
os.Exit(8)
}
psa.print_dest = s2
argno++
continue
break
default:
fmt.Fprintf(os.Stderr,
"%s: unknown option %s\n", progname, s1)
usage()
os.Exit(9)
break
} /* end switch */
}
if (DEBUG) {
fmt.Fprintf(os.Stderr, "DEBUG: before check for filename arg\n")
fmt.Fprintf(os.Stderr, "DEBUG: argno = %d\n", argno)
}
if (argno <= (ac - 1)) {
psa.in_filename = av[argno]
/* check if file exists */
fi, err := os.Stat(psa.in_filename)
if (err != nil) {
fmt.Fprintf(os.Stderr, "%s: input file \"%s\" does not exist\n",
progname, psa.in_filename)
os.Exit(10)
}
/* check if file is readable */
if ((fi.Mode() & os.ModePerm & 0x4) == 0) {
fmt.Fprintf(os.Stderr, "%s: input file \"%s\" exists but cannot be read\n",
progname, psa.in_filename)
os.Exit(11)
}
}
if (psa.start_page <= 0) {
os.Exit(112)
}
if (!(psa.end_page > 0 && psa.end_page >= psa.start_page)) {
os.Exit(113)
}
if (psa.page_len <= 1) {
os.Exit(114)
}
if (!(psa.page_type == 'l' || psa.page_type == 'f')) {
os.Exit(115)
}
if (DEBUG) {
fmt.Fprintf(os.Stderr, "DEBUG: psa->start_page = %d\n", psa.start_page)
fmt.Fprintf(os.Stderr, "DEBUG: psa->end_page = %d\n", psa.end_page)
fmt.Fprintf(os.Stderr, "DEBUG: psa->page_len = %d\n", psa.page_len)
fmt.Fprintf(os.Stderr, "DEBUG: psa->page_type = %c\n", psa.page_type)
fmt.Fprintf(os.Stderr, "DEBUG: psa->print_dest = %s\n", psa.print_dest)
fmt.Fprintf(os.Stderr, "DEBUG: psa->in_filename = %s\n", psa.in_filename)
}
}
/*================================= process_input() ===============*/
func process_input(sa selpg_args) {
var fin *os.File
//var fout *os.File
var s1 string
//var crc string
//var c int
//var line string
var line_ctr int
var page_ctr int
var wc io.Writer
var err error
var cmd *exec.Cmd
/* set the input source */
if (len(sa.in_filename) == 0) {
fin = os.Stdin
} else {
fin, err = os.OpenFile(sa.in_filename, os.O_RDONLY, 0666)
if (err != nil) {
fmt.Fprintf(os.Stderr, "%s: could not open input file \"%s\"\n",
progname, sa.in_filename)
os.Exit(12)
}
}
/* use setvbuf() to set a big buffer for fin, for performance */
inbuf := bufio.NewReader(fin)
/* set the output destination */
if (len(sa.print_dest) == 0) {
//fout = os.Stdout
// wc = bufio.NewWriter(os.Stdout)
} else {
(os.Stdout).Sync()
fmt.Sprintf(s1, "lp -d%s", sa.print_dest)
cmd = exec.Command(s1)
tmp, err := cmd.StdinPipe()
wc = tmp
cmd.Start()
//fout = popen(s1, "w");
if (err != nil) {
fmt.Fprintf(os.Stderr, "%s: could not open pipe to \"%s\"\n",
progname, s1)
os.Exit(13)
}
}
/* begin one of two main loops based on page type */
if (sa.page_type == 'l') {
line_ctr = 0;
page_ctr = 1;
for (true) {
line, err := inbuf.ReadString('\n')
if (err != nil || io.EOF == err) {
break
}
line_ctr++
if (line_ctr > sa.page_len) {
page_ctr++
line_ctr = 1
}
if ( (page_ctr >= sa.start_page) && (page_ctr <= sa.end_page) ) {
if (len(sa.print_dest) == 0) {
fmt.Fprintf(os.Stdout, "%s", line)
//wc.Write([]byte(line))
} else {
wc.Write([]byte(line))
}
}
}
} else {
page_ctr = 1;
for (true) {
c, err := inbuf.ReadByte()
if (err != nil) {
break
}
if (c == '\f') {
page_ctr++
}
if ( (page_ctr >= sa.start_page) && (page_ctr <= sa.end_page) ) {
bs := []byte{c}
//wc.Write(bs)
if (len(sa.print_dest) == 0) {
fmt.Fprintf(os.Stdout, "%c", c)
//wc.Write([]byte(line))
} else {
//wc.Write([]byte(line))
wc.Write(bs)
}
//putc(c, fout);
}
}
}
/* end main loop */
if (page_ctr < sa.start_page) {
fmt.Fprintf(os.Stderr,
"%s: start_page (%d) greater than total pages (%d), no output written\n",
progname, sa.start_page, page_ctr)
} else if (page_ctr < sa.end_page) {
fmt.Fprintf(os.Stderr,
"%s: end_page (%d) greater than total pages (%d), less output than expected\n",
progname, sa.end_page, page_ctr)
}
if (err != nil) {
s1 = "error,haha"
fmt.Fprintf(os.Stderr, "%s: system error [%s] occurred on input stream fin\n",
progname, s1)
os.Exit(14)
} else {
//wc.Flush()
fmt.Fprintf(os.Stderr, "%s: done\n", progname)
}
}
/*================================= usage() =======================*/
func usage() {
fmt.Fprintf(os.Stderr,
"\nUSAGE: %s -sstart_page -eend_page [ -f | -llines_per_page ] [ -ddest ] [ in_filename ]\n", progname)
}
/*================================= EOF ===========================*/