
本文介绍如何使用 go 的 bufio.scanner 正确解析并逐行输出 exec.command 执行外部命令(如 df -h)的标准输出,避免常见误区(如直接打印 scanner 实例),并提供完整、健壮的示例代码。
本文介绍如何使用 go 的 bufio.scanner 正确解析并逐行输出 exec.command 执行外部命令(如 df -h)的标准输出,避免常见误区(如直接打印 scanner 实例),并提供完整、健壮的示例代码。
在 Go 中调用外部命令(如 df -h)后,其标准输出是一个字节流([]byte)。若需按行处理(例如逐行打印、过滤或解析),不能直接将 stdout 传给 bufio.NewScanner——因为 NewScanner 期望接收一个实现了 io.Reader 接口的对象(如 *bytes.Reader 或 io.ReadCloser),而 cmd.Output() 返回的是 []byte,需先包装为 bytes.NewReader(stdout)。
以下是修正后的完整实现,包含错误处理、逐行扫描和清晰输出:
package main
import (
"bufio"
"fmt"
"os/exec"
"strings"
)
func main() {
app := "df"
arg0 := "-h"
cmd := exec.Command(app, arg0)
stdout, err := cmd.Output()
if err != nil {
fmt.Printf("命令执行失败: %v\n", err)
return
}
// 将字节切片转换为 io.Reader(关键步骤)
scanner := bufio.NewScanner(strings.NewReader(string(stdout)))
// 逐行读取并打印
lineNum := 1
for scanner.Scan() {
line := scanner.Text()
fmt.Printf("%d: %s\n", lineNum, line)
lineNum++
}
// 检查扫描过程中是否发生错误(如解码问题)
if err := scanner.Err(); err != nil {
fmt.Printf("读取输出时出错: %v\n", err)
}
}⚠️ 注意事项:
- ❌ 错误写法:
bufio.NewScanner(stdout)会编译失败(stdout是[]byte,非io.Reader); - ✅ 正确做法:使用
strings.NewReader(string(stdout))或bytes.NewReader(stdout)包装; -
scanner.Text()返回不带换行符的字符串,适合直接处理; - 务必调用
scanner.Err()检查扫描阶段是否出现 I/O 或编码错误; - 若命令输出量极大,可考虑使用
cmd.StdoutPipe()配合流式处理,避免内存积压。
通过上述方式,你不仅能逐行打印结果,还能灵活对每一行做日志记录、正则匹配、结构化解析等操作,是 Go 中调用系统命令并处理文本输出的标准实践。


















