2017-04-01 64 views
0

我想从一个进程获取标准输出到另一个不使用标准输入的进程,因为那个用于另一个目的。将标准输出到命令本身需要从自己的标准输入读取

总之我要完成这样的事情:

echo "a" >&4 
cat | grep -f /dev/fd/4 

我得到了它运行使用文件作为源文件描述符4,但是这不是我想要的:

# Variant 1 
cat file | grep -f /dev/fd/4 4<pattern 

# Variant 2 
exec 4<pattern 
cat | grep -f /dev/fd/4 
exec 4<&- 

我最好的尝试是,但我得到以下错误信息:

# Variant 3 
cat | ( 
    echo "a" >&4 
    grep -f /dev/fd/4 
) <&4 

错误消息:

test.sh: line 5: 4: Bad file descriptor 

什么是最好的方法来实现这一目标?

回答

4

你并不需要使用多个数据流来做到这一点:

$ printf foo > pattern 
$ printf '%s\n' foo bar | grep -f pattern 
foo 

如果不是你想使用一个命令的输出作为输入-f你可以使用一个process substitution一个静态文件:

$ printf '%s\n' foo bar | grep -f <(echo foo) 
foo 
+0

啊,我得到了进程替换错误:即使'grep -f <(echo FOO)-i'也可以工作。 但是没有办法做到这一点。我在我看来更可读...(但也许这是一个错误的假设) – doak

+0

不,实际上它更可读;) – doak

+0

你可以看看一些类似的问题:http://stackoverflow.com/questions/19715318/ – doak

0

对于缺乏进程替换POSIX壳,(例如dashashyash)。

如果命令允许字符串输入,(grep允许的话),以及包含搜索目标的输入字符串不是特别大,(即字符串不超过length limit for the command line),总有command substitution

$ printf '%s\n' foo bar baz | grep $(echo foo) 
foo 

或者,如果输入文件是多行,用分离引述搜索项 '\ n' 的工作方式相同grepOR\|

$ printf '%s\n' foo bar baz | grep "$(printf "%s\n" foo bar)" 
foo 
bar 
+0

输入很大,并有多行('grep'的几种模式)。 @ l0b0解决方案匹配得更好。 – doak

+0

@doak,Re“*几行​​”:那听起来不那么大。对于上述代码的*多行*版本失败,整个目标字符串列表的字节长度将需要(几乎)大于'getconf ARG_MAX'的输出,(* eg *在我目前的系统上那是* 2097152 *)。 – agc

+1

这是一个很好的选择,没有工艺替代。不过,我不喜欢多行版本中额外的'sed'。 – doak

相关问题