Bash 进程替换
发表于 2008年5月22日
除了常见的输入/输出重定向形式之外,shell 还识别一种叫做 *进程替换* 的东西。虽然没有作为输入/输出重定向的一种形式进行文档化,但它的语法和效果是相似的。
进程替换的语法是
<(list) or >(list)其中每个 *list* 是一个命令或命令管道。进程替换的效果是使每个 list 就像一个文件一样。这是通过在文件系统中给 list 一个 *名称*,然后在命令行中替换该名称来完成的。list 通过连接到命名管道或使用以下文件来获得名称:/dev/fd(如果操作系统支持)。通过这样做,命令只会看到一个文件名,而不知道它正在从命令管道读取或写入。
要将命令管道替换为输入文件,语法是
command ... <(list) ...要将命令管道替换为输出文件,语法是
command ... >(list) ...
起初,进程替换可能看起来相当没有意义,例如,你可能会想到一些简单的事情,比如
uniq <(sort a)对文件进行排序,然后找到其中的唯一行,但更常见(也更方便)的写法是
sort a | uniq当你有多个要连接到单个命令的命令管道时,进程替换的威力就体现出来了。
例如,给定两个文件
# cat a e d c b a # cat b g f e d c b要查看这两个未排序文件中每个文件独有的行,你可以这样做
# sort a | uniq >tmp1 # sort b | uniq >tmp2 # comm -3 tmp1 tmp2 a f g # rm tmp1 tmp2通过进程替换,我们可以用一行代码完成所有这些
# comm -3 <(sort a | uniq) <(sort b | uniq) a f g
根据您的 shell 设置,您可能会收到类似于以下内容的错误消息
syntax error near unexpected token `('当您尝试使用进程替换时,尤其是在 shell 脚本中使用时。 进程替换不是 POSIX 兼容功能,因此可能需要通过以下方式启用:
set +o posix小心不要尝试类似的事情
if [[ $use_process_substitution -eq 1 ]]; then set +o posix comm -3 <(sort a | uniq) <(sort b | uniq) fi命令set +o posix不仅启用了进程替换的执行,还启用了语法的识别。 因此,在上面的示例中,shell 会在 "set" 命令执行之前尝试解析进程替换语法,因此仍然将进程替换语法视为非法。
当然,请注意,并非所有 shell 都支持进程替换,这些示例将在 bash 中有效。