首页 系统教程 操作系统 从入门到精通,学会Linux重定向和管道工具加速你的工作流程!

从入门到精通,学会Linux重定向和管道工具加速你的工作流程!

Feb 09, 2024 pm 11:36 PM
linux linux教程 linux系统 linux操作系统 linux命令 外壳脚本 嵌入式linux linux入门 linux学习

提高工作效率、操作系统优化、自动化等是每个IT从业者所追求的目标。在Linux操作系统中,能够熟练使用重定向和管道命令行工具是必须掌握的技能之一。本文将通过实例详解重定向和管道工具的使用方法及原理。

我很喜欢 Linux 系统,尤其是 Linux 的一些设计很漂亮,比如可以将一些复杂的问题分解成若干小问题,通过管道符和重定向机制灵活地用现成的工具解决,写成 shell 脚本就很高效。

从入门到精通,学会Linux重定向和管道工具加速你的工作流程!

本文就分享一下我在实践中使用重定向和管道符遇到的一些坑,搞明白一些底层原理,写脚本的效率能提升不少。

> 和 >> 重定向符的坑

先说第一个问题,执行如下命令会发生什么?

$ cat file.txt > file.txt
登录后复制

读取再写入同一个文件,感觉什么也不会发生对吧?

实际上,上述命令运行的结果是清空file.txt文件中的内容。

PS:有的 Linux 发行版可能会直接报错,可以执行catfile.txt绕开这个检测。

前文 Linux 进程和文件描述符 说过,程序本身没有必要关心自己的标准输入/输出指向哪里,是 shell 通过管道符和重定向符号修改了程序的标准输入/输出的位置。

所以执行cat file.txt > file.txt这个命令时,shell 会先打开file.txt,由于重定向符号是>,所以文件中的内容会被清空,然后 shell 将cat命令的标准输出设置为file.txt,这时候cat命令才开始执行。

也就是如下过程:

1、shell 打开file.txt并清空其内容。
2、shell 将cat命令的标准输出指向file.txt文件。
3、shell 执行cat命令,读了一个空文件。
4、cat命令将空字符串写入标准输出(file.txt文件)。

所以,最后的结果就是file.txt变成了空文件。

我们知道,>会清空目标文件,>>会在目标文件尾部追加内容,那么如果将重定向符>改成>>会怎样呢?

$ echo hello world > file.txt # 文件中只有一行内容 
$ cat file.txt >> file.txt # 这个命令会死循环 
登录后复制

file.txt中首先被写入一行内容,执行cat file.txt >> file.txt后预期的结果应该是两行内容。

但是很遗憾,运行结果并不符合预期,而是会死循环不断向file.txt中写入 hello world,文件很快就会变得很大,只能用 Control+C 停止命令。

这就有意思了,为什么会死循环呢?其实稍加分析就可以想到原因:

首先要回忆cat命令的行为,如果只执行cat命令,就会从命令行读取键盘输入的内容,每次按下回车,cat命令就会回显输入,也就是说,cat命令是逐行读取数据然后输出数据的。

那么,cat file.txt >> file.txt命令的执行过程如下:

1、打开file.txt,准备在文件尾部追加内容。
2、将cat命令的标准输出指向file.txt文件。
3、cat命令读取file.txt中的一行内容并写入标准输出(追加到file.txt文件中)。
4、由于刚写入了一行数据,cat命令发现file.txt中还有可以读取的内容,就会重复步骤 3。

以上过程,就好比一边遍历列表,一遍往列表里追加元素一样,永远遍历不完,所以导致我们的命令死循环。

> 重定向符和 | 管道符配合

我们经常会遇到这样的需求:截取文件的前 XX 行,其余的都删除。

在 Linux 中,head命令可以完成截取文件前几行的功能:

$ cat file.txt # file.txt 中有五行内容 
1 
2 
3 
4 
5 
$ head -n 2 file.txt # head 命令读取前两行 
1 
2 
$ cat file.txt | head -n 2 # head 也可以读取标准输入 
1 
2 
登录后复制

如果我们想保留文件的前 2 行,其他的都删除,可能会用如下命令:

$ head -n 2 file.txt > file.txt 
登录后复制

但是这就犯了前文说的错误,最后file.txt会被清空,不能实现我们的需求。

那我们是这样写命令是否可以避坑呢:

$ cat file.txt | head -n 2 > file.txt 
登录后复制
登录后复制

结论是不行,文件内容依然会被清空。

What?是不是管道漏了,把数据全漏掉了?

前文 Linux 进程和文件描述符 也说过管道符的实现原理,本质上就是将两个命令的标准输入和输出连接起来,让前一个命令的标准输出作为下一个命令的标准输入。

但是,如果你认为这样写命令可以得到预期的结果,那可能是因为你认为管道符连接的命令是串行执行的,这是一个常见的错误,实际上管道符连接的多个命令是并行执行的。

你可能以为,shell 会先执行cat file.txt命令,正常读取file.txt中的所有内容,然后把这些内容通过管道传递给head -n 2 > file.txt命令。

虽然这时候file.txt中的内容会被清空,但是head并没有从文件中读取数据,而是从管道读取数据,所以应该可以向file.txt正确写入两行数据。

但实际上,上述理解是错误的,shell 会并行执行管道符连接的命令,比如说执行如下命令:

$ sleep 5 | sleep 5 
登录后复制

shell 会同时启动两个sleep进程,所以执行结果是睡眠 5 秒,而不是 10 秒。

这是有点违背直觉的,比如这种常见的命令:

$ cat filename | grep 'pattern' 
登录后复制

直觉好像是先执行cat命令一次性读取了filename中所有的内容,然后传递给grep命令进行搜索。

但实际上是cat和grep命令是同时执行的,之所以能得到预期的结果,是因为grep ‘pattern’会阻塞等待标准输入,而cat通过 Linux 管道向grep的标准输入写入数据。

执行下面这个命令能直观感受到cat和grep是在同时执行的,grep在实时处理我们用键盘输入的数据:

$ cat | grep 'pattern' 
登录后复制

说了这么多,再回顾一开始的问题:

$ cat file.txt | head -n 2 > file.txt 
登录后复制
登录后复制

cat命令和head会并行执行,谁先谁后不确定,执行结果也就不确定。

如果head命令先于cat执行,那么file.txt就会被先清空,cat也就读取不到任何内容;反之,如果cat先把文件的内容读取出来,那么可以得到预期的结果。

不过,通过我的实验(将这种并发情况重复 1w 次)发现,file.txt被清空这种错误情况出现的概率远大于预期结果出现的概率,这个暂时还不清楚是为什么,应该和 Linux 内核实现进程和管道的逻辑有关。

解决方案

说了这么多管道符和重定向符的特点,如何才能避免这个文件被清空的坑呢?

最靠谱的办法就是不要同时对同一个文件进行读写,而是通过临时文件的方式做一个中转。

比如说只保留file.txt文件中的头两行,可以这样写代码:

# 先把数据写入临时文件,然后覆盖原始文件

$ cat file.txt | head -n 2 > temp.txt && mv temp.txt file.txt
登录后复制

这是最简单,最可靠,万无一失的方法。

你如果嫌这段命令太长,也可以通过apt/brew/yum等包管理工具安装moreutils包,就会多出一个sponge命令,像这样使用:

# 先把数据传给 sponge,然后由 sponge 写入原始文件 
$ cat file.txt | head -n 2 | sponge file.txt 
登录后复制

sponge这个单词的意思是海绵,挺形象的,它会先把输入的数据「吸收」起来,最后再写入file.txt,核心思路和我们使用临时文件时类似的,这个「海绵」就好比一个临时文件,就可以避免同时打开同一个文件进行读写的问题。

在Linux操作系统中,重定向和管道是非常有用的命令行工具,可以让我们更好地掌握系统的运行状态和信息。掌握相关技能能够帮助我们更好地进行系统优化和自动化工作,从而更好地提高工作效率。相信通过本文的介绍,读者对重定向和管道的原理和使用方法都有了更为深入的了解。

以上是从入门到精通,学会Linux重定向和管道工具加速你的工作流程!的详细内容。更多信息请关注PHP中文网其他相关文章!

本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

Video Face Swap

Video Face Swap

使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热工具

记事本++7.3.1

记事本++7.3.1

好用且免费的代码编辑器

SublimeText3汉化版

SublimeText3汉化版

中文版,非常好用

禅工作室 13.0.1

禅工作室 13.0.1

功能强大的PHP集成开发环境

Dreamweaver CS6

Dreamweaver CS6

视觉化网页开发工具

SublimeText3 Mac版

SublimeText3 Mac版

神级代码编辑软件(SublimeText3)

vscode需要什么电脑配置 vscode需要什么电脑配置 Apr 15, 2025 pm 09:48 PM

VS Code 系统要求:操作系统:Windows 10 及以上、macOS 10.12 及以上、Linux 发行版处理器:最低 1.6 GHz,推荐 2.0 GHz 及以上内存:最低 512 MB,推荐 4 GB 及以上存储空间:最低 250 MB,推荐 1 GB 及以上其他要求:稳定网络连接,Xorg/Wayland(Linux)

vscode 无法安装扩展 vscode 无法安装扩展 Apr 15, 2025 pm 07:18 PM

VS Code扩展安装失败的原因可能包括:网络不稳定、权限不足、系统兼容性问题、VS Code版本过旧、杀毒软件或防火墙干扰。通过检查网络连接、权限、日志文件、更新VS Code、禁用安全软件以及重启VS Code或计算机,可以逐步排查和解决问题。

notepad怎么运行java代码 notepad怎么运行java代码 Apr 16, 2025 pm 07:39 PM

虽然 Notepad 无法直接运行 Java 代码,但可以通过借助其他工具实现:使用命令行编译器 (javac) 编译代码,生成字节码文件 (filename.class)。使用 Java 解释器 (java) 解释字节码,执行代码并输出结果。

vscode是什么 vscode是干什么用的 vscode是什么 vscode是干什么用的 Apr 15, 2025 pm 06:45 PM

VS Code 全称 Visual Studio Code,是一个由微软开发的免费开源跨平台代码编辑器和开发环境。它支持广泛的编程语言,提供语法高亮、代码自动补全、代码片段和智能提示等功能以提高开发效率。通过丰富的扩展生态系统,用户可以针对特定需求和语言添加扩展程序,例如调试器、代码格式化工具和 Git 集成。VS Code 还包含直观的调试器,有助于快速查找和解决代码中的 bug。

vscode 可以用于 mac 吗 vscode 可以用于 mac 吗 Apr 15, 2025 pm 07:36 PM

VS Code 可以在 Mac 上使用。它具有强大的扩展功能、Git 集成、终端和调试器,同时还提供了丰富的设置选项。但是,对于特别大型项目或专业性较强的开发,VS Code 可能会有性能或功能限制。

VSCode怎么用 VSCode怎么用 Apr 15, 2025 pm 11:21 PM

Visual Studio Code (VSCode) 是一款跨平台、开源且免费的代码编辑器,由微软开发。它以轻量、可扩展性和对众多编程语言的支持而著称。要安装 VSCode,请访问官方网站下载并运行安装程序。使用 VSCode 时,可以创建新项目、编辑代码、调试代码、导航项目、扩展 VSCode 和管理设置。VSCode 适用于 Windows、macOS 和 Linux,支持多种编程语言,并通过 Marketplace 提供各种扩展。它的优势包括轻量、可扩展性、广泛的语言支持、丰富的功能和版

Linux的主要目的是什么? Linux的主要目的是什么? Apr 16, 2025 am 12:19 AM

Linux的主要用途包括:1.服务器操作系统,2.嵌入式系统,3.桌面操作系统,4.开发和测试环境。Linux在这些领域表现出色,提供了稳定性、安全性和高效的开发工具。

git怎么查看仓库地址 git怎么查看仓库地址 Apr 17, 2025 pm 01:54 PM

要查看 Git 仓库地址,请执行以下步骤:1. 打开命令行并导航到仓库目录;2. 运行 "git remote -v" 命令;3. 查看输出中的仓库名称及其相应的地址。

See all articles