Go中如何将io.Writer转换成字符串(将两个管道连接的exec.Command输出的标准输出获取成字符串)

server/2024/9/23 3:31:16/

假设我们需要在Go中运行下面的命令:

PS -A | grep wget

这里需要写成两个exec.Command,如下,第一个命令为cmd,第二个为cmd2

cmd := exec.Command("PS", "-A")
cmd2 := exec.Command("grep", "wget")

然后使用管道连接二者的标准输出和标准输入,需要注意第一个命令cmd的标准输出应该使用cmd.StdoutPipe(),而不是Stdout,如下(忽略了错误err和其处理):

cmd2.Stdin, _ = cmd.StdoutPipe()

因为cmd.Stdout是一个io.Writer,是一个写入器,因为这个输出是要写入某些地方的。而同理,cmd2.Stdin是一个io.Reader,是一个读取器,用来读取一些地方的内容。二者直接赋值的话会出现类型不匹配的错误。所以需要使用StdoutPipe()函数,这个函数会返回一个io.Reader。(这里比较绕,所以可能需要想一下)

在获取了输出之后,需要将其转换成字符串的话,可以使用bytes.Buffer来获取cmd2.Stdout的标准输出(记住这是个io.Writer),然后再转换成字符串。

我们是是无法直接将io.Writer直接写入到bytes.Buffer之中的,你可能会说bytes.Buffer不是有两个方法ReadFromWriteTo吗?

前者只能读取io.Reader的,后者只能写入io.Writer,所以我们需要一个管道来将io.Writer转换成io.Reader,然后才能读取或复制其内容。而这个转换就是再使用一次管道,如下:

var buf bytes.Buffer
r, w, _ := os.Pipe()
cmd2.Stdout = w
go buf.ReadFrom(r)

这里buf.ReadFrom(r)必须使用 goroutine,也就是让这个代码并行运行,所以在前面加上go

这里的go buf.ReadFrom(r)也可以使用go io.Copy(&buf, r)替代,效果一样。

因为命令执行的顺序是先启动cmd2,然后运行cmdcmd运行完之后,数据流通过管道传递给cmd2cmd2再运行。不然cmd运行的时候的标准输出是空的,就会一直等。

buf.ReadFrom(r)cmd2也是同理,不过由于这是行代码,无法使用start启动它,所以并行就行了。

接下来的命令如下:

cmd2.Start()
cmd.Run()
cmd2.Wait()

这里就是前面说的流程:cmd2启动,运行cmd,让cmd2等待cmd的输出。

需要注意一点:go buf.ReadFrom(r)其实可以放在上面代码中,除了最后一行之外的任何地方。之所以不能放在最后是因为这时候都运行完了,再读取就是空的了。

然后将其转换成字符串:

str := buf.String()

打印看看:

fmt.Println("123" + str + "123")

之所以要前后都加上"123"是为了避免调试的时候把输出到标准输出文件的内容当成这里打印的。

结果如下:

% go run main.go
12360651 ttys010    0:00.00 grep wget
123

这里分成两行是因为获取的时候grep wget后面有个\n,这里看不出来,如果%#v格式化打印就能看到了。

完整代码如下:

func main() {cmd := exec.Command("PS", "-A")cmd2 := exec.Command("grep", "wget")cmd2.Stdin, _ = cmd.StdoutPipe()var buf bytes.Bufferr, w, _ := os.Pipe()cmd2.Stdout = w// 下面这行代码可以替换为:go io.Copy(&buf, r)go buf.ReadFrom(r)cmd2.Start()cmd.Run()cmd2.Wait()str := buf.String()fmt.Println("123" + str + "123")
}

希望能帮到有需要的人~


http://www.ppmy.cn/server/34199.html

相关文章

自动驾驶融合定位系列教程五:惯性导航误差分析

自动驾驶融合定位系列教程五:惯性导航误差分析 一、概述 在定位领域的几乎所有多传感器融合系统中,都有IMU存在,而且,IMU是定位系统的主线与核心(对此可能很多人并不同意,但是我仍然坚定地坚持这一观点&a…

自动驾驶领域涉及的五种算法

在自动驾驶领域,涉及到以下五种算法: 感知算法:感知算法用于从传感器数据中提取环境信息,包括物体检测、目标跟踪、道路识别等。这些算法可以通过视觉传感器(如摄像头)、激光雷达、雷达等来获取环境信息。 …

Android Studio学习笔记——数据库存储

Android Studio学习笔记——数据库存储 6.1持久化技术简介6.2 文件存储将数据存储到文件中从文件中读取数据 6.3 SharedPreferences存储6.3.1 将数据存储到是SharedPreferences中6.3.2 从SharedPreferences中读取数据6.3.3 实现记住密码功能 6.4 SQLite数据库存储6.4.1 创建数据…

hadoop学习---Hive分桶表的机制及其查询优化方案

什么是分桶表? 分桶是将数据集分解成更容易管理的若干部分的一个技术,是比分区更为细粒度的数据范围划分。 主要是用于分文件的,在建表的时候,指定按照那些字段执行分桶操作,并可以设置需要分多少个桶,当插…

基于 Dockerfile 部署 LNMP 架构

目录 前言 1、任务要求 2、Nginx 镜像创建 2.1 建立工作目录并上传相关安装包 2.2 编写 Nginx Dockerfile 脚本 2.3 准备 nginx.conf 配置文件 2.4 生成镜像 2.5 创建 Nginx 镜像的容器 2.6 验证nginx 3、Mysql 镜像创建 3.1 建立工作目录并上传相关安装包 3.2 编写…

【DevOps】Jenkins 集成Docker

目录 1. 安装 Docker 和 Jenkins 2. 在 Jenkins 中安装 Docker 插件 3. 配置 Docker 连接 4. 创建 Jenkins Pipeline 5. 示例 Pipeline 脚本 6. 运行 Jenkins Job 7. 扩展功能 8、docker配置测试连接的时候报错处理 将 Docker 与 Jenkins 集成可以实现持续集成和持续交…

漫谈音频深度伪造技术

作为人工智能时代的新型媒体合成技术,深度伪造技术近年来在网络媒体中的涉及领域越发广泛、出现频次越发频繁。据路透社报道,2023年,社交媒体网站上发布50万个深度伪造的语音和视频。 1、深度伪造技术的五个方面 音频深度伪造技术&#xff…

一种算法分类方式及其应用

在计算机科学领域,算法是解决问题的有效方法,而对算法进行分类有助于理解它们的特性、优劣以及在不同场景下的应用。常见的算法分类方法,包括按设计思想、问题类型、数据结构和应用领域等,每一类算法会对应有其典型和实际应用。 算…