请选择 进入手机版 | 继续访问电脑版
查看: 62|回复: 1

[经验分享] 基于bash中的tee用法讲解

[复制链接]

签到天数: 104 天

[LV.6]签到达人

发表于 2018-10-8 17:18:18 | 显示全部楼层 |阅读模式
1.tee多重定向
tee [options] FILE1 FILE2 FILE3...
tee的作用是将一份标准输入多重定向,一份重定向到标准输出/dev/stdout,然后还将标准输入重定向到每个文件FILE中。

例如:

$ cat alpha.log | tee file1 file2 file3 | cat
$ cat alpha.log | tee file1 file2 file3 >/dev/null
上面第一个命令将alpha.log的文件内容重定向给file{1..3}和标准输出通过管道传递给cat;
上面第二个命令将alpha.log的文件内容重定向给file{1..3}和/dev/null。

tee重定向给多个命令
写多了脚本的人可能遇到过这样一种需求:将一份标准输入,重定向到多个命令中去。大概是这样的:

                      | CMD1
                    ↗
        INPUT | tee
                    ↘
                      | CMD2
其实bash自身的特性就能实现这样的需求,通过重定向到子shell中,就能模拟一个文件重定向行为:

cat alpha.txt | tee >(grep -E "a|b") >(grep -E "d|b|c")
上面的命令将alpha.txt文件内容重定向为3份:一份给第一个grep命令,一份给第二个grep命令,一份给标准输出。假如alpha.txt的内容是a b c d e5个字母分别占用5行(每行一个字母),上面的输出结果如下:

a
b
c
d
e  # 前5行是重定向到/dev/stdout的
a
b  # 这2行是重定向给第一个grep后的执行结果
b
c
d  # 这3行是重定向给第二个grep后的执行结果
如果不想要给标准输出的那份重定向,加上>/dev/null:

cat alpha.txt | tee >(grep -E "a|b") >(grep -E "d|b|c") >/dev/null
tee重定向给多个命令时的问题
但是必须注意,tee将数据重定向给不同命令时,这些命令是独立执行的,它们都会各自打开一个属于自己的STDOUT,如果它们都重定向到标准输出,由于涉及到多个不同的/dev/stdout,它们的结果将出现两个问题:

不保证有序性
因为跨了命令,交互式模式下(默认标准输出为屏幕)可能会出现命令行隔断的问题(非交互式下不会有问题)
例如:

$ cat alpha.txt | tee >(grep -E "a|b") >(grep -E "d|b|c") >/dev/null
$ a     # 结果直接出现在提示符所在行
b
b
c
d

$ cat alpha.txt | tee >(grep -E "a|b") >(grep -E "d|b|c") >/dev/null
b
c      # 这次的结果和上次的顺序不一样
d
a
b
这两个问题,在写脚本过程中必须解决。

对于第二个问题:不同/dev/stdout同时输出时在屏幕上交叉输出的问题,只需将它们再次重定向走即可,这样两份不同的/dev/stdout都再次同时作为一份标准输入:

$ cat alpha.txt | tee >(grep -E "a|b") >(grep -E "d|b|c") >/dev/null | cat
对于第一个问题:不同/dev/stdout同时输出时,输出顺序的随机性,这个没有好方法,只能在各命令行中将各自的结果保存到文件中:

$ cat alpha.txt | tee >(grep -E "a|b" >file1) >(grep -E "d|b|c" >file2) >/dev/null
所以,tee在重定向到多个命令中是有缺陷的,或者说用起来非常不方便,只要将各命令的结果各自保存时,才能一切按照自己的预期进行。那么,pee登场了,多重定向非常好用的一个命令。

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

返回顶部