shell 展开中的进程替换可以说是非常难懂的一部分,它的语法为有两种
>(list)
或
<(list)
语法中的list为一个或多个命令,用分号分隔。
这两种语法的进程替换都被展开为一个文件描述符 /dev/fd/63
,区别在于 >(list)
只接受输入,而<(list)
只能作为输出。
在 << The Linux Command Line>> 一书中提到了这样一个事,代码如下
echo david | read user
echo $user # 输出结果为空
通过管道把echo的输出作为read命令的输入,然后输入保存到user变量中,但是输出user变量的结果却为空。这是因为管道后的命令是在子shell中执行的,因此当子shell执行完毕后,回到当前shell时,user变量是不可见的。
而书中的解决办法如下
read user <<< "david"
echo $user # 结果为david
这是利用 here strings 语法作为 read 命令的输入。
其实可以通过进程替换来解决管道的问题,如下
read user < <(echo david)
echo $user # 结果为david
由于 <(echo david)
可以被替换为 /dev/fd/63
,因此上面的命令等价于下面的命令
read user < /dev/fd/63
这是一个简单的重定向问题。
通过这个例子我们了解了<(list)
语法,其实我们也可以推导出>(list)
的使用方式,如下
echo david > >(read user; echo $user) # 输出为david
这个使命等价如下命令
echo david > /dev/fd/63
总结
不管是>(list)
语法,还是<(list)
语法,其实我们就把它当作一个文件,这个文件包含list中的所有命令,并且这个文件是打开的,文件描述符为 /dev/fd/63
。