Process substitution(进程替换)


转自:http://www.linuxsir.org/main/doc/abs/abs3.7cnhtm/process-sub.html

abs(Advanced Bash-Scripting Guide)的中文版:http://www.linuxsir.org/main/doc/abs/abs3.7cnhtm/index.html

第22章. 进程替换

进程替换命令替换(command substitution)很相似. 命令替换把一个命令的结果赋给一个变量,例如 dir_contents=`ls -al`xref=$( grep word datafile). 进程替换则是把一个进程的输出回馈给另一个进程 (换句话说,它把一个命令的结果发送给另一个命令).

命令替换的一般形式

由圆括号括起的命令

>(command)

<(command)

启动进程替换. 它是用/dev/fd/<n>文件把在圆括号内的进程的处理结果发送给另外一个进程. [1] (译者注:实际上现代的UNIX类操作系统提供的/dev/fd/n文件是与文件描述相关的,整数n指的就是在进程运行时对应数字的文件描述符)

Note

"<" 或or ">" 与圆括号之间是没有空格的. 如果加了空格将会引起错误信息.

 bash$ echo >(true)
/dev/fd/63

bash$ echo <(true)
/dev/fd/63
Bash在两个 文件描述符(file descriptors)之间创建了一个管道, --fInfOut--. true命令的标准输入被连接到fOut(dup2(fOut, 0)), 然后Bash把 /dev/fd/fIn作为参数传给 echo.如果系统的 /dev/fd/<n>文件不够时,Bash会使用临时文件. (Thanks, S.C.)

进程替换能比较两个不同命令之间的输出,或者甚至相同命令不同选项的输出.

 bash$ comm <(ls -l) <(ls -al)
total 12
-rw-rw-r-- 1 bozo bozo 78 Mar 10 12:58 File0
-rw-rw-r-- 1 bozo bozo 42 Mar 10 12:58 File2
-rw-rw-r-- 1 bozo bozo 103 Mar 10 12:58 t2.sh
total 20
drwxrwxrwx 2 bozo bozo 4096 Mar 10 18:10 .
drwx------ 72 bozo bozo 4096 Mar 10 17:58 ..
-rw-rw-r-- 1 bozo bozo 78 Mar 10 12:58 File0
-rw-rw-r-- 1 bozo bozo 42 Mar 10 12:58 File2
-rw-rw-r-- 1 bozo bozo 103 Mar 10 12:58 t2.sh

用进程替换来比较两个不同目录的内容 (考察哪些文件名是相同的,哪些是不同的):

   1 diff <(ls $first_directory) <(ls $second_directory)

其他一些进程替换的用法和技巧:

   1 cat <(ls -l)
2 # 等同于 ls -l | cat

4 sort -k 9 <(ls -l /bin) <(ls -l /usr/bin) <(ls -l /usr/X11R6/bin)
5 # 列出系统中3个主要的'bin'目录的所有文件,并且按文件名排序.
6 # 注意是三个明显不同的命令输出回馈给'sort'.


9 diff <(command1) <(command2) # 给出两个命令输出的不同之处.
10 
11 tar cf >(bzip2 -c > file.tar.bz2) $directory_name
12 # 调用"tar cf /dev/fd/?? $directory_name",和"bzip2 -c > file.tar.bz2".
13 #
14 # 因为/dev/fd/<n>的系统属性,
15 # 所以两个命令之间的管道不必是命名的.
16 #
17 # 这种效果可以模仿出来.
18 #
19 bzip2 -c < pipe > file.tar.bz2&
20 tar cf pipe $directory_name
21 rm pipe
22 # 或者
23 exec 3>&1
24 tar cf /dev/fd/4 $directory_name 4>&1 >&3 3>&- | bzip2 -c > file.tar.bz2 3>&-
25 exec 3>&-
26 
27 
28 # Thanks, St磒hane Chazelas

有个读者给我发来下面关于进程替换的有趣例子A.

   1 # 摘自SuSE发行版中的代码片断:

3 while read des what mask iface; do
4 # 这里省略了一些命令 ...
5 done < <(route -n)


8 # 为了测试它,我们来做些动作.
9 while read des what mask iface; do
10  echo $des $what $mask $iface
11 done < <(route -n)
12 
13 # 输出:
14 # Kernel IP routing table
15 # Destination Gateway Genmask Flags Metric Ref Use Iface
16 # 127.0.0.0 0.0.0.0 255.0.0.0 U 0 0 0 lo
17 
18 
19 
20 # 由 St閜hane Chazelas给出的,一个更容易理解的等价代码是:
21 route -n |
22  while read des what mask iface; do # 管道的输出被赋给了变量.
23  echo $des $what $mask $iface
24  done # 这样就取回了和上面一样的输出.
25  # 但是, Ulrich Gayer指出 . . .
26  #+ 这个简单版本的等价代码在while循环中使用了一个子shell,
27  #+ 因此当管道结束后变量会被毁掉.
28 
29 
30 
31 # 更进一步, Filip Moritz解释了上面两个例子之间有一个细微的不同之处
32 #+ 如下所示.
33 
34 (
35 route -n | while read x; do ((y++)); done
36 echo $y # $y 仍然没有被声明或设置
37 
38 while read x; do ((y++)); done < <(route -n)
39 echo $y # $y的值为 route -n 输出的行数
40 )
41 
42 # 一般来说
43 (
44 : | x=x
45 # 看上去是启动了一个子shell
46 : | ( x=x )
47 # 但
48 x=x < <(:)
49 # 实际上不是
50 )
51 
52 # 当解析csv或类似的东西时非常有用.
53 # 事实上,这就是SuSE原本的代码片断所要实现的功能.

[1]

这与命名管道(named pipe)(临时文件)有相同的作用, 事实上命名管道同样在进程替换中被使用.

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值