Shell中的管道与xargs

来源:互联网 发布:全国最好的专科 知乎 编辑:程序博客网 时间:2024/05/01 22:27

在《程序员修炼之道:从小工到专家》这本书里,解答41给了一个Shell版本的测试器。

试了一下无法运行,问题出在下面这句话上:

#!/bin/shCMD="java dbc.dbc_ex"failcount=0expect_okay() {    if echo "$*" | $CMD #>/dev/null 2>&1    then        :    else        echo "FAILED! $*"        failcount='expr $failcount + 1'    fi}

在if这行,echo "$*"输出的参数,没有办法通过管道传递给后面的命令。

不知道作者的运行环境是什么,我在AIX和Cygwin上试验都失败了。


原因很简单,管道是通过stdin来传递的,而无法从stdin读取输入的命令,比如本例中的java,无法取到管道中的参数。

而awk等可以从stdin获取输入的命令则可以直接从管道获取数据。


解决方案很简单,增加xargs命令,改为:

#!/bin/shCMD="java dbc.dbc_ex"failcount=0expect_okay() {    if echo "$*" | xargs $CMD #>/dev/null 2>&1        then        :    else        echo "FAILED! $*"        failcount='expr $failcount + 1'    fi}
xargs可以从管道中获取参数,然后再将参数和后面的命令组合起来执行。(如果参数过长还会自动拆分并调用多次。)

这样等于变相解决了无法直接获取管道数据的命令和管道结合使用的问题。

详细说明参见:http://blog.csdn.net/peteryxk/article/details/1622491


顺便说一下>/dev/null 2>&1这句命令的意思是将stdout和stderr全部重定向到/dev/null中,也就是将产生的所有信息丢弃,避免输出。

常用于夜间批处理的场合。(本例中被注释掉了)

2>&1这种写法可以避免重定向时产生两个管道同时访问同一个目标。

具体说明参见:http://viplin.blog.51cto.com/241472/99568

原创粉丝点击