我有一个程序,将信息写入标准输出和标准错误,我需要用grep处理标准错误,把标准错误放在一边。
使用临时文件,可以分两步完成:
command > /dev/null 2> temp.file
grep 'something' temp.file
但是,在没有临时文件的情况下,如何使用一个命令和管道实现这一点呢?
我有一个程序,将信息写入标准输出和标准错误,我需要用grep处理标准错误,把标准错误放在一边。
使用临时文件,可以分两步完成:
command > /dev/null 2> temp.file
grep 'something' temp.file
但是,在没有临时文件的情况下,如何使用一个命令和管道实现这一点呢?
当前回答
首先将stderr重定向到stdout -管道;然后将stdout重定向到/dev/null(不改变stderr的去向):
command 2>&1 >/dev/null | grep 'something'
有关各种I/O重定向的详细信息,请参阅Bash参考手册中的重定向章节。
Note that the sequence of I/O redirections is interpreted left-to-right, but pipes are set up before the I/O redirections are interpreted. File descriptors such as 1 and 2 are references to open file descriptions. The operation 2>&1 makes file descriptor 2 aka stderr refer to the same open file description as file descriptor 1 aka stdout is currently referring to (see dup2() and open()). The operation >/dev/null then changes file descriptor 1 so that it refers to an open file description for /dev/null, but that doesn't change the fact that file descriptor 2 refers to the open file description which file descriptor 1 was originally pointing to — namely, the pipe.
其他回答
对于那些想要将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
首先将stderr重定向到stdout -管道;然后将stdout重定向到/dev/null(不改变stderr的去向):
command 2>&1 >/dev/null | grep 'something'
有关各种I/O重定向的详细信息,请参阅Bash参考手册中的重定向章节。
Note that the sequence of I/O redirections is interpreted left-to-right, but pipes are set up before the I/O redirections are interpreted. File descriptors such as 1 and 2 are references to open file descriptions. The operation 2>&1 makes file descriptor 2 aka stderr refer to the same open file description as file descriptor 1 aka stdout is currently referring to (see dup2() and open()). The operation >/dev/null then changes file descriptor 1 so that it refers to an open file description for /dev/null, but that doesn't change the fact that file descriptor 2 refers to the open file description which file descriptor 1 was originally pointing to — namely, the pipe.
在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
如果你正在使用Bash,那么使用:
command >/dev/null |& grep "something"
http://www.gnu.org/software/bash/manual/bashref.html#Pipelines