Shell 将一个命令的输出发送给另一个命令,Unix shell脚本最棒的特性之一就是可以轻松地将多个命令组合起来生成输出。一个命令的输出可以作为另一个命令的输入,而这个命令的输出又会传递至下一个命令,以此类推。这种命令组合的输出可以被存储在变量中。本章将演示如何组合多个命令并读取其输出。
预备知识
命令输入通常来自于stdin
或参数。输出可以发送给stdout
或stderr
。当我们组合多个命令时,通常将stdin
用于输入,stdout
用于输出。
在这种情况下,这些命令被称为过滤器(filter)。我们使用管道(pipe)连接每个过滤器,管道操作符是|
。例如:
$ cmd1 | cmd2 | cmd3
这里我们组合了3个命令。cmd1
的输出传递给cmd2
,cmd2
的输出传递给cmd3
,最终的输出(来自cmd3
)会出现在显示器中或被导入某个文件。
实战演练
我们通常使用管道并配合子shell的方式来组合多个命令的输出。
(1) 先从组合两个命令开始:
$ ls | cat -n > out.txt
ls
(列出当前目录内容)的输出被传给cat -n
,后者为通过stdin
所接收到的输入内容加上行号,然后将输出重定向到文件out.txt。
(2) 将命令序列的输出赋给变量:
cmd_output=$(COMMANDS)
这种方法叫作子shell法。例如:
cmd_output=(ls | cat -n)
echocmd_output
另一种方法叫作反引用(有些人也称它为反标记),也可以用于存储命令输出:
cmd_output=`COMMANDS`
例如:
cmd_output=`ls | cat -n`
echo $cmd_output
反引用与单引号可不是一回事,该字符位于键盘的 ~ 键上。
补充内容
命令分组的方法不止一种。
- 利用子shell生成一个独立的进程
子shell本身就是独立的进程。可以使用()
操作符来定义一个子shell。
(1)pwd
命令可以打印出工作目录的路径。
(2)cd
命令可以将当前目录修改成指定的目录。
$> pwd
/
$> (cd /bin; ls)
awk bash cat...
$> pwd
/
当命令在子shell中执行时,不会对当前shell造成任何影响;所有的改变仅限于该子shell内。例如,当用cd命令改变子shell的当前目录时,这种变化不会反映到主shell环境中。
- 通过引用子shell的方式保留空格和换行符
假设我们使用子shell或反引用的方法将命令的输出保存到变量中,为了保留输出的空格和换行符(\n
),必须使用双引号。例如:
$ cat text.txt
1
2
3
$ out=$(cat text.txt)
$ echo $out
1 2 3 # 丢失了1、2、3中的\n
$ out="$(cat text.txt)"
$ echo $out
1
2
3