摘要本文呢会介绍在 shell 编程中经常使用到的重定向的相关知识,以及文本处理的一些常用命令。本文主要有以下的内容,标准输入输出-stdio(包含三种 I/O 流);管道符的简单使用;重定向(重定向输入,重定向输出,重定向错误);简单的文本处理(「排序」与「合并」)和 xargs 命令。
简介
这篇文章将着重介绍在 shell 编程中经常使用到的重定向的相关知识,以及文本处理的一些常用命令。本文会分为以下几个内容进行介绍:
- 标准输入输出-stdio(包含三种 I/O 流);
- 管道符的简单使用;
- 重定向(重定向输入,重定向输出,重定向错误);
- 简单的文本处理(「排序」与「合并」);
- xargs 命令(将字符串按指定符号进行分割);
标准输入输出-stdio
对于 Linux 内核中的标准 I/O 库 stdio 提供了一个高效的缓存 I/O 流接口。一般情况下,每个程序在启动时都会有三个 stream(流)在启动时被预定义,一个用于输入,一个用于输出,还有一个用于打印诊断或者错误信息。
对于 linux 系统中来说,读取标准输入和打印标准输出的地方默认情况下都是所使用的终端。对应 shell 中常使用的三种标准 I/O 流:
stdin,标准输入流;stdout,标准输出流;stderr,诊断错误信息流;
输入流-stdin
输入流(input stream)被称作标准输入(standard input),缩写形式即为 stdin。在程序启动时,与 stdin 关联的整数文件描述符为 0。
这里我们引入文件描述符的概念(百度百科的定义):
- 内核(kernel)利用文件描述符(file descriptor)来访问文件。
- 文件描述符是非负整数。打开现存文件或新建文件时,内核会返回一个文件描述符。读写文件也需要使用文件描述符来指定待读写的文件。
- 实际上,它是一个索引值,指向内核为每一个进程所维护的该进程打开文件的记录表。当程序打开一个现有文件或者创建一个新文件时,内核向进程返回一个文件描述符。
输出流-stdout
输出流(output stream)被称作标准输出(standard output),缩写形式即为 stdout。在程序启动时,与 stdout 关联的整数文件描述符为 1。
错误流-stderr
错误流(error stream)被称作标准错误输出(standard error),缩写形式即为 stderr。在程序启动时,与 stderr 关联的整数文件描述符为 2。
Linux 管道符
Linux 管道来说可以用于 Linux 程序之间,Linux 命令之间以及 Linux 程序和命令之间的通信。 在 shell 中,管道符(pipeline)是 shell 编程中众多控制操作符其中的一个,用来分隔一个或多个命令的序列。shell 编程中管道符号是竖杠符号 |(但是有时会使用到 |& 符号,这种用法会同时包含「输出流」和「错误流」,该用法将在后面的内容中详细描述)。
在 shell 中使用管道的格式如下,代表着 command1 的标准输出作为 command2 的标准输入使用,而 command2 的标准输出又作为 command3 的标准输入使用:
- command1 | command2 | command3
例如下面一个简单的例子。第一个命令使用 echo 来输出文字,第二个命令使用 grep 将第一个 echo 的输出当作输出:

重定向
在执行命令之前,我们可以使用 shell 解释的特殊符号重定其输入和输出。下面会分别来将「重定向输入」,「重定向输出」,
重定向输入
重定向输入的一般格式如下:
- [n] < file
上面命令代表的意思是将输入从文件描述符为 n 的文件重定向到 file。不指定 n 时,文件描述符 n 为 0,为标准输入。代表着将输入从标准输入重定向到 file 中(简单理解为,将文件 file 的内容作为输入)。
我们来看一个例子。首先新建一个文件,在其中写入 Happy New Year!。如下所示:

接着将该文件作为 grep 的输入,使用 grep 查找 Happy:

重定向输出
重定向输出的格式如下所示:
- [n] > file
这里代表的意思是将输出从文件描述符为 n 的文件重定向到 file。不指定 n 时,文件描述符 n 为 1,为标准输出。代表着将输出从标准输出重定向到 file 中。
这里需要注意的是,如果 file 不存在,将会创建 file,如果 file 存在,文件大小将被设为 0,然后输出,即覆盖原有文件的内容。如果需要将输出内容附加到文件中,需要使用 >> 来替代 > 符号。
我们来看一个例子。我们将 echo 的输出保存在文件 file1 中,然后查看文件内容:

重定向 stdout 和 stderr
这里我们会用到管道符部分提到的 |& 符号,使用的格式如下:
- command1 |& command2
上面的命令表示将 command1 命令的「标准输出」和「标准错误」作为 command2 的标准输入。不同于 |,这里多了一个标准错误的选项。
下面来看一个例子。我们查看当前目录下一个不存在的文件,这个时候会出现「标准错误」。我们使用 |& 符号将这个标准错误作为 cat 的输入,接着将 cat 的输出重定向到 file 文件:

除此之外,还可以使用 &> 符号达到一样的效果。如下所示,将「标准错误」输出到 file 文件中:

更常用的一种用法是将「标准输入」和「标准错误」分别重定向到两个文件。例如 command 2>err.log 1>info.log 这个命令表示 err.log 和 info.log 分别用来存储 command 命令的标准错误和标准输出。下面是一个例子:

简单的文本处理
Linux 的一些命令支持对文件进行简单的操作。例如现在有一个文件,存储着个人信息(包含姓名和年龄),如下所示:
- name1 30
- name2 20
- name3 25
对文件进行排序
我们可以使用 sort 命令对文本内容进行排序。关于 sort 命令的详细用法可以使用 sort --help 查看,这里我们简单介绍一些常用的参数。
-u去除重复行;-t指定分隔字符,例如上面我们使用的空格字符,默认为空格;-o输出到指定文件;-k指定使用某一列进行排序;-r修改默认的升序排序为降序;
例如我们对上面的文件,按照年龄进行降序排序,最终的结果如下所示:

对文件的合并
有两种文件合并的方式,分别是 paste 和 join 的方式。
paste命令可以将多个文件以列对列的方式加以合并;join命令可以将多个文件中有相同特征的列进行合并;
现在我们新建一个文件,里面包含每个学生和他的学号,如下所示:
- name1 man
- name2 woman
- name4 man
我们首先来看一下paste 命令的效果(可以看到只是单纯的合并):

如果这个时候我们使用join 命令,则会尝试进行合并(保留共有内容的行):

xargs 命令
xargs 命令可以从标准输入构建和执行命令。xargs 常用来给其他命令传递参数,从标准输入读取数据,默认情况下使用空格或者换行符作为默认定界符,忽略空白行,并且在没有指定命令的时候,默认将数据传递给 /bin/echo ,即我们常用的 echo 命令作为参数。下面我们将介绍一些常用的参数:
-a使用该参数指定从文件中读取,而不是标准输入;-d自定义定界符;-n每行的最多参数个数;
例如下面的例子中,我们使用 x 作为「定界符」,每行显示一个,将原本一行的内容分开:

菜鸟笔记