Go语言-执行系统命令以及获取命令行参数

摘要

  • Go 执行系统命令
  • 命令行参数
  • 标准输入输出

Go 执行系统命令

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55

//阻塞式的执行外部shell命令的函数,等待执行完毕并返回标准输出
func exec_shell(s string) (string, error){
//函数返回一个*Cmd,用于使用给出的参数执行name指定的程序
//fmt.Println(s)
cmd := exec.Command("/bin/bash", "-c", s)

//读取io.Writer类型的cmd.Stdout,再通过bytes.Buffer(缓冲byte类型的缓冲器)将byte类型转化为string类型(out.String():这是bytes类型提供的接口)
var out bytes.Buffer
cmd.Stdout = &out

//Run执行c包含的命令,并阻塞直到完成。 这里stdout被取出,cmd.Wait()无法正确获取stdin,stdout,stderr,则阻塞在那了
err := cmd.Run()
//if err != nil {
// fmt.Println(err)
//}

return out.String(), err
}

func execCommand(commandName string, params []string) [][]string {
//函数返回一个*Cmd,用于使用给出的参数执行name指定的程序
cmd := exec.Command(commandName, params...)

//显示运行的命令
fmt.Println(cmd.Args)
//StdoutPipe方法返回一个在命令Start后与命令标准输出关联的管道。Wait方法获知命令结束后会关闭这个管道,一般不需要显式的关闭该管道。
stdout, err := cmd.StdoutPipe()
var lines [][]string

if err != nil {
fmt.Println(err)
return lines
}

cmd.Start()
//创建一个流来读取管道内内容,这里逻辑是通过一行一行的读取的
reader := bufio.NewReader(stdout)

//实时循环读取输出流中的一行内容
for {
line, err2 := reader.ReadString('\n')
if err2 != nil || io.EOF == err2 {
break
}
//fmt.Println(line)
lines = append(lines, strings.Split(line, " "))
}
fmt.Println(lines[2][3])

//阻塞直到该命令执行完成,该命令必须是被Start方法开始执行的
cmd.Wait()
return lines
//return true
}

Go命令行参数

os.Args

1
2
3
4
fmt.Println(os.Args)//打印切片内容
for i := 0; i < len(os.Args); i++ {
fmt.Println(os.Args[i])
}

其中第一个参数为可执行文件的名字,其他的参数都是以字符串的形式,存储在slice os.Args当中,可以通过for range 语句来遍历所有的参数

1
2
3
4
5
6
7
8
9
10
11
12
13
package main

import (
"fmt"
"os"
"strconv"
)

func main () {
for idx, args := range os.Args {
fmt.Println("参数" + strconv.Itoa(idx) + ":", args)
}
}

flag

上面的参数解析只是从命令行当中把参数存储在os.Args切片当中,应用的时候,不是很方便,特别是,编译好的一个可执行文件,别人不知道如何使用的时候,可以使用Go内置的flag包对参数进行说明,并可设置默认值。

1
flag.Type("flagName",defaultValue,"help message") *Type

flag包依据Type的类型,和参数标志flagName,对标志flagName设置默认值和帮助信息,最终返回一个指向该类型的指针,可以通过指针是否为空来判断命令行里是否使用该标志参数,下面是一个例子。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
package main
import (
"fmt"
"flag"
)

var n = flag.Int("n", 0, "int类型参数")
var b = flag.Bool("b", false, "bool类型参数")
var s = flag.String("s", "", "string类型参数")

func main() {
flag.Parse()
fmt.Println("-n:", *n)
fmt.Println("-b:", *b)
fmt.Println("-s:", *s)
fmt.Println("其他参数:", flag.Args())
}

Go 标准输入输出

1
2
3
4
5
6
7
func main() {
input := bufio.NewScanner(os.Stdin)//初始化一个扫表对象
for input.Scan() {//扫描输入内容
line := input.Text()//把输入内容转换为字符串
fmt.Println(line)//输出到标准输出
}
}