Unix/Linux - Shell 输入/输出重定向



本章将详细讨论 Shell 输入/输出重定向。大多数 Unix 系统命令从您的终端接收输入,并将生成的输出发送回您的终端。命令通常从标准输入读取其输入,默认情况下,标准输入是您的终端。类似地,命令通常将其输出写入标准输出,这同样也是您的终端。

输出重定向

通常用于标准输出的命令输出可以轻松地改定向到文件。此功能称为输出重定向。

如果将符号 `>`file 附加到任何通常将其输出写入标准输出的命令,则该命令的输出将写入文件,而不是您的终端。

检查以下 **who** 命令,该命令将命令的完整输出重定向到 users 文件。

$ who > users

请注意,终端上没有显示任何输出。这是因为输出已从默认的标准输出设备(终端)重定向到指定的文件。您可以检查 users 文件的完整内容:

$ cat users
oko         tty01   Sep 12 07:30
ai          tty15   Sep 12 13:32
ruth        tty21   Sep 12 10:10
pat         tty24   Sep 12 13:07
steve       tty25   Sep 12 13:03
$

如果命令的输出重定向到一个文件,并且该文件已经包含一些数据,则这些数据将丢失。请考虑以下示例:

$ echo line 1 > users
$ cat users
line 1
$

您可以使用 `>>` 运算符将输出追加到现有文件,如下所示:

$ echo line 2 >> users
$ cat users
line 1
line 2
$

输入重定向

就像命令的输出可以重定向到文件一样,命令的输入也可以从文件重定向。如同使用 **大于号 >** 用于输出重定向,**小于号 <** 用于重定向命令的输入。

通常从标准输入获取输入的命令可以以这种方式从文件重定向其输入。例如,要计算上面生成的 users 文件中的行数,您可以执行以下命令:

$ wc -l users
2 users
$

执行后,您将收到以下输出。您可以通过从 users 文件重定向 **wc** 命令的标准输入来计算文件中的行数:

$ wc -l < users
2
$

请注意,wc 命令的两种形式产生的输出有所不同。在第一种情况下,文件名 users 与行数一起列出;在第二种情况下,则没有。

在第一种情况下,wc 知道它正在从 users 文件读取输入。在第二种情况下,它只知道它正在从标准输入读取输入,因此它不显示文件名。

Here Document

**Here Document** 用于将输入重定向到交互式 shell 脚本或程序。

我们可以通过为交互式程序或交互式 shell 脚本提供所需的输入,在 shell 脚本中运行交互式程序,而无需用户操作。

**Here Document** 的一般形式为:

command << delimiter
document
delimiter

在这里,shell 将 **<<** 运算符解释为一个指令,读取输入直到找到包含指定分隔符的行。然后,所有直到包含分隔符的行之前的输入行都将被送入命令的标准输入。

分隔符告诉 shell **Here Document** 已完成。如果没有分隔符,shell 将永远继续读取输入。分隔符必须是一个不包含空格或制表符的单个单词。

以下是用于计算总行数的命令 **wc -l** 的输入:

$wc -l << EOF
   This is a simple lookup program 
	for good (and bad) restaurants
	in Cape Town.
EOF
3
$

您可以使用 **Here Document** 使用您的脚本打印多行,如下所示:

#!/bin/sh

cat << EOF
This is a simple lookup program 
for good (and bad) restaurants
in Cape Town.
EOF	

执行后,您将收到以下结果:

This is a simple lookup program
for good (and bad) restaurants
in Cape Town.

以下脚本运行与 **vi** 文本编辑器的会话,并将输入保存到文件 **test.txt** 中。

#!/bin/sh

filename=test.txt
vi $filename <<EndOfCommands
i
This file was created automatically from
a shell script
^[
ZZ
EndOfCommands

如果使用 vim 作为 vi 运行此脚本,则您可能会看到如下输出:

$ sh test.sh
Vim: Warning: Input is not from a terminal
$

运行脚本后,您应该会看到以下内容添加到文件 **test.txt** 中:

$ cat test.txt
This file was created automatically from
a shell script
$

丢弃输出

有时您需要执行命令,但不想在屏幕上显示输出。在这种情况下,您可以通过将其重定向到文件 ** /dev/null** 来丢弃输出:

$ command > /dev/null

这里 command 是您要执行的命令的名称。文件 ** /dev/null** 是一个特殊文件,它会自动丢弃其所有输入。

要丢弃命令的输出及其错误输出,请使用标准重定向将 **STDERR** 重定向到 **STDOUT**:

$ command > /dev/null 2>&1

这里 **2** 代表 **STDERR**,**1** 代表 **STDOUT**。您可以通过将 STDOUT 重定向到 STDERR 来在 STDERR 上显示消息,如下所示:

$ echo message 1>&2

重定向命令

以下是您可以用于重定向的完整命令列表:

序号 命令 & 说明
1

pgm > file

pgm 的输出重定向到 file

2

pgm < file

程序 pgm 从 file 读取输入

3

pgm >> file

pgm 的输出追加到 file

4

n > file

来自描述符为 **n** 的流的输出重定向到 file

5

n >> file

来自描述符为 **n** 的流的输出追加到 file

6

n >& m

将来自流 **n** 的输出与流 **m** 合并

7

n <& m

将来自流 **n** 的输入与流 **m** 合并

8

<< tag

标准输入从此处开始,直到下一行开头处的 tag

9

|

获取一个程序或进程的输出,并将其发送到另一个程序或进程

请注意,文件描述符 **0** 通常是标准输入 (STDIN),**1** 是标准输出 (STDOUT),**2** 是标准错误输出 (STDERR)。

广告