LinuxSir.cn,穿越时空的Linuxsir!

 找回密码
 注册
搜索
热搜: shell linux mysql
楼主: home_king

命令输出放进多个管道,并让管道命令并行化[深刻理解重定向及IO重定向详解]

[复制链接]
 楼主| 发表于 2004-4-3 08:02:41 | 显示全部楼层
最初由 yongjian 发表
我不太理解home_king所说的的“并行解压缩”的概念。能否解释一下你的例子是如何实现的呢? 我想我的问题是for loop是在tar命令完成后还是一个文件tar着呢就for到下一个文件呢?

for只是一个循环结构,实际的步骤是它的循环体,在这个例子中就是解压缩。
使用了bash的wait来等待每个放进后台的解压缩进程的结束,以免出现"孤儿进程",并协调它们的并行操作。在超线程或多CPU架构上,这样的协同进程是高效的。
 楼主| 发表于 2004-4-3 08:07:51 | 显示全部楼层
最初由 yongjian 发表
不知这种算不算是管道并行呢:
cat < data1 > data2
将 data1中的内容导出同时导入到另一个文件。但是用的不同的文件描述符吧。

嗯,也算吧。不过,我要求的是"输出方向多管道并行",而不是双向。
但即使是双向,正如我上面提及的"替换进程"概念,也是很难实现的。尤其把同一个输出放进多管道中去。(注意,这样cmd1|cmd2只是一个单管道)
发表于 2004-4-3 09:33:30 | 显示全部楼层
bash的很多特性是仿效ksh的,当然还有它自己的一些新特性,就协进程而言,bash目前还没有实现。
楼主所举例子的只是一个循环,然后在循环中丢一些后台命令跑,仅仅是并行处理而已。就目前所知只有ksh有专门的协处理命令。bash可以用命名管道实现,不过有些繁琐,不如ksh简洁易读。
另外,能否请楼主解释一下什么是多管道运行?
请问有几个程序产生输出,又有几个程序处理这些输出?
最好举例说明一下。
 楼主| 发表于 2004-4-3 09:37:07 | 显示全部楼层
的确,现在bash的协同进程不好。It works like chaos!
比如说有一个命令command1,要求它产生的输出不能保存为文件,并同时用两个过滤命令command2与command3来处理它的输出。
发表于 2004-4-3 11:56:56 | 显示全部楼层
最初由 home_king 发表
的确,现在bash的协同进程不好。It works like chaos!
比如说有一个命令command1,要求它产生的输出不能保存为文件,并同时用两个过滤命令command2与command3来处理它的输出。

在ksh的书中,有关dbx命令可以实现,我去找找看~
发表于 2004-4-3 14:05:12 | 显示全部楼层
如下例,echo 产生test字串的输出,其中tr命令将其转换为TEST,sed命令将t替换为9,输出均为标准输出,也可根据需要将其重定向。bash下结果为
  1. r2007@www r2007 $ echo test|tee >(tr 'a-z' 'A-Z')|sed 's/t/9/'               
  2. 9est
  3. TEST
  4.             
复制代码
 楼主| 发表于 2004-4-3 14:10:00 | 显示全部楼层
  1. r2007@www r2007 $ echo test|tee >(tr 'a-z' 'A-Z')|sed 's/t/9/'               
  2. 9est
  3. TEST
  4.             
复制代码

好,充分利用了Bash的进程替换特色以及管道。
我再延伸一下,可以用纯"进程替换"来实现这点吗?正如以下的命令。
  1. cmp <(cat filename1) <(cat filename2)
复制代码
发表于 2004-4-3 14:31:15 | 显示全部楼层
首先“进程替换”,我不知道它确切的中文通称,是有前提的,只有命令提供文件名参数时才有实际意义。假如有这么一个cmd1命令,它支持两个文件参数,而且它可以将其输出同时保存在这两个文件中,那么就可以这样
  1. cmd1 >(cmd2) >(cmd3)
复制代码

原则是,理解cmd1的命令格式,将其中应该提供输出文件名的位置,替换为>(cmd)
由于没有找到合适的cmd1命令,所以我现在无法提供例子。
其实cmp <(cat filename1) <(cat filename2)这个例子中,cmp就接受两个文件名参数,所以可以使用两个进程替换。
发表于 2004-4-3 14:31:53 | 显示全部楼层
最初由 r2007 发表
如下例,echo 产生test字串的输出,其中tr命令将其转换为TEST,sed命令将t替换为9,输出均为标准输出,也可根据需要将其重定向。bash下结果为
  1. r2007@www r2007 $ echo test|tee >(tr 'a-z' 'A-Z')|sed 's/t/9/'               
  2. 9est
  3. TEST
  4.             
复制代码

谢谢,又学到了一招~~:thank
 楼主| 发表于 2004-4-3 15:18:33 | 显示全部楼层
最初由 r2007 发表
只有命令提供文件名参数时才有实际意义。假如有这么一个cmd1命令,它支持两个文件参数,而且它可以将其输出同时保存在这两个文件中,那么就可以这样
  1. cmd1 >(cmd2) >(cmd3)
复制代码

其实cmp <(cat filename1) <(cat filename2)这个例子中,cmp就接受两个文件名参数,所以可以使用两个进程替换。

同意r2007的看法。进程替换的规则确实如此。
在此我姑且引用《Learning the Bash shell》(为易于理解,略加调整)来给出"进程替换"的概念。
一个命名管道是一个临时文件,其功能类似于一个有名字的管道。
list是通过命名管道将其输入或输出连接到某处的一个进程。
该(进程)替换有两种形式,一种是对该进程的输入:>(list);一种是对进程的输出:<(list)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 返回顶部 返回列表