今天来给大家介绍一个非常好用的shell编程技巧,即进程替换(Process substitution)。
进程替换可以将一个进程(程序)的输入或输出当做一个文件来使用。
它的两种使用形式为:<(cmd)
或>(cmd)
.
需要注意的是,<
和>
与(
之间不能有空格!
下面通过一个示例来介绍进程替换的具体用法。
假如我有一个几种编程语言的使用用户数目的文件,其内容如下(虚构数字请勿当真):
$ cat num_users.tsv
programming_language num_users
Python 2000
Linux 3000
R 3500
C 2000
Java 2000
此时我还有一个几种编程语言的起源时间的文件,其内容如下:
$ cat history.tsv
programming_language orgin_date
R 1980
Python 1989
如果我想通过第二个文件(history.tsv
)从第一个文件(num_users.tsv
)中取出来R和Python的用户数目,那么可以运行的命令为:
$ cut -f1 history.tsv |sed '1d' > a # 首先取出第一列,并去掉第一行(header)
$ cat a # 其内容如下
R
Python
$ grep -Fwf a num_users.tsv # 在num_users.tsv文件中搜索文件a中的内容,搜索结果如下
Python 2000
R 3500
可以发现上面一共用了三行命令,其过程为:
- 首先将
history.tsv
文件的内容取出来存入到一个临时文件a
中 - 其次使用
grep
在num_users.tsv
文件中搜索文件a
中的关键词
如果使用了进程替换,那么将不需要产生临时文件a
,其命令如下:
$ grep -Fwf <(cut -f1 history.tsv |sed '1d') num_users.tsv
Python 2000
R 3500
在上述命令中<(cut -f1 history.tsv |sed '1d')
的内容与前面文件a
的内容完全一致,且作用也一样,因此可以得到相同的结果。
可以发现,使用了进程替换以后便可以一行命令完成上述需求,无需产生中间文件。
进程替换的应用还有很多,这里再举另一个比较简单的例子,即比较两个文件的第一列是否一致。
这两个文件(a.tsv
和b.tsv
)的内容如下:
$ cat a.tsv
programming_language orgin_date
R 1980
Python 1989
$ cat b.tsv
programming_language num_users
R 3500
Python 2000
由于这两个文件的第一列一样,但是后面的列不同,所以不能直接使用diff
命令来比较这两个文件。
要比较这两个文件的第一列是否一致,传统的命令如下:
$ cut -f1 a.tsv > 1
$ cut -f1 b.tsv > 2
$ diff 1 2
而使用进程替换的命令如下:
$ diff <(cut -f1 a.tsv) <(cut -f1 b.tsv)
一行命令即可搞定!非常简洁!
参考链接:https://www.gnu.org/software/bash/manual/html_node/Process-Substitution.html
最后
本文同步发表于微信公众号:水木的生信与编程世界,如果觉得本文对您有帮助欢迎关注公众号,我会持续分享更多关于生信的分析经验和实用技巧。