3-4 管线(pipeline)观念与运用 将一个指令的标准输出复位向,做为下一个指令的标准输入,像这种连结两个指令间标准输出、输入的特殊功能,便称为管线(pipeline)。在 C shell 中定义了两个关于管线功能的特殊符号。如下: “|” 只定向标准输出(stdout) “|&” 定向标准输出与标准错误(stdout and stderr) 先让我们来看看一个例子: 2 % who
akira ttyp0 Sep 9 17:49 (akirahost)
akk ttyp1 Sep 9 17:49 (akirahost)
simon ttyp2 Sep 9 17:49 (akirahost)
3 % who > file.a ; wc -l < file.a ; \rm -f file.a
3
4 % who | wc -l
3 从上面的例子中,要计算 who 指令的输出有几行,以输出复位向的做法是,先将 who 指令输出复位向到一个档案“file.a”中,再将该档案复位向到指令 wc -l 来计算行数。最后再将产生的资料档案“file.a”清除。这过程中有三个硬磁的 I/O 动作。但如果使用管线的方法如行 4 所示,它根本没有硬磁的 I/O 动作,是不是比行 3 所下的指令方便多了呢。而且不需产生任何档案,省略的 I/O 动作,对使用效率来说是比较好的使用方式。 我们再来看看下面这个例子: % find ~ -name "*.dat" -print | rm 上面的指令是用指令 find 找寻 home 目录下档名为“*.dat”并将它列出,再将列出的讯息运用管线通入指令 rm 去将这些档案清除。说起来好像是一点问题也没有,其实是一点用也没有。要不然马上上机试一试。这个指令的错不在于指令 find 或运用了管线,而是在于指令 rm 身上,因为它的引数不接受标准输入。所以你无法这样使用。不过指令 find 本身的语法有支持像上面的运用,如下示: % find ~ -name "*.dat" -exec rm -i "{}" \; 当指令 find 在找到一个相符的档名时会执行指令 rm -i,让你键入 y 或 n 来决定是否要清除该档案,之后,指令 find 会再继续寻找相符的档名来做同样的动作。这样的功能便与上面那个使用管线不成的指令作用相同了。 所以在管线的运用时一定得注意前后指令的关系,及是否指令接受标准输入等问题。你越用心去尝试将可得到越方便的越佳的使用效率。看下面这个运用: % ps axu | egrep 'cron|nfsd|pcnfsd' | egrep -v egrep | lpr 从一个系统讯息经过数个管线的连接,将这个系统讯息筛选处理成我们所要的资讯,并直接将它由列表机印出。或者是像下面的运用: % cat files | grep pattern | sort -u | more 像这类的运用都是相当得宜的作法。 3-4-1 相关的辅助指令 - tee 指令的功能 对管线的功能而言,并无法像输出复位向可产生档案。这是管线功能的不足与限制之处。但不要紧, UNIX 有一指令可填补这项缺撼,这便是 tee 指令。当行 4 指令修改为“who | tee file.a | wc -l”,则指令 who 的输出一方面由 tee 指令储存到档案“file.a”中,一方面又 pipe 到指令 wc -l 去计算 who 输出的行数。这个指令你可用在备份档案的指令,特别是当你想一面在荧幕上查看档案备份的情况,而又希望将备份档案的讯息储存成档案时。如下例: 1 % tar cvf /dev/rst8 /user1 /user2 |& tee backup.data 另外该指令也提供了一个 -a 的选项,来让你能将讯息加到指定档案的内容之后。请看以下的运用。 2 % date | tee -a log.log
Sun Nov 26 22:15:15 CST 1995 在指令 2 中,我们再一次使用 tee 指令将指令 date 的输出加到档案“backup.data”中,但因为指令 tee 有加上选项 -a,所以并不会将原档案的内容清除掉。怎么样是不是很好用呢? |