我有一个程序,将信息写入标准输出和标准错误,我需要用grep处理标准错误,把标准错误放在一边。
使用临时文件,可以分两步完成:
command > /dev/null 2> temp.file
grep 'something' temp.file
但是,在没有临时文件的情况下,如何使用一个命令和管道实现这一点呢?
我有一个程序,将信息写入标准输出和标准错误,我需要用grep处理标准错误,把标准错误放在一边。
使用临时文件,可以分两步完成:
command > /dev/null 2> temp.file
grep 'something' temp.file
但是,在没有临时文件的情况下,如何使用一个命令和管道实现这一点呢?
当前回答
这将重定向command1 stderr到command2 stdin,同时保留command1 stdout原样。
exec 3>&1
command1 2>&1 >&3 3>&- | command2 3>&-
exec 3>&-
摘自LDP
其他回答
把这些最好的答案结合起来,如果你有:
命令2> >(grep -v something 1>&2)
...然后所有的stdout被保留为stdout,所有的stderr被保留为stderr,但是你不会在stderr中看到任何包含字符串“something”的行。
这有一个独特的优点,即不反转或丢弃stdout和stderr,也不将它们混在一起,也不使用任何临时文件。
或者将标准错误输出和标准输出交换,使用:
command 3>&1 1>&2 2>&3
这将创建一个新的文件描述符(3),并将其分配到与1(标准输出)相同的位置,然后将fd 1(标准输出)分配到与fd 2(标准错误)相同的位置,最后将fd 2(标准错误)分配到与fd 3(标准输出)相同的位置。
标准误差现在可以作为标准输出,旧的标准输出保留在标准误差中。这可能有点过分,但希望它能提供更多关于Bash文件描述符的详细信息(每个进程有9个可用的文件描述符)。
对于那些想要将stdout和stderr永久重定向到文件的人,在stderr上使用grep,但保留stdout以将消息写入tty:
# save tty-stdout to fd 3
exec 3>&1
# switch stdout and stderr, grep (-v) stderr for nasty messages and append to files
exec 2> >(grep -v "nasty_msg" >> std.err) >> std.out
# goes to the std.out
echo "my first message" >&1
# goes to the std.err
echo "a error message" >&2
# goes nowhere
echo "this nasty_msg won't appear anywhere" >&2
# goes to the tty
echo "a message on the terminal" >&3
在Bash中,你也可以使用进程替换重定向到子shell:
command > >(stdout pipe) 2> >(stderr pipe)
对于手头的案子:
command 2> >(grep 'something') >/dev/null
这将重定向command1 stderr到command2 stdin,同时保留command1 stdout原样。
exec 3>&1
command1 2>&1 >&3 3>&- | command2 3>&-
exec 3>&-
摘自LDP