如何管道标准错误,而不是标准输出?

我有一个程序,写信息到stdoutstderr ,我需要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参考手册中的重定向一章。

请注意,I / O重定向的顺序是从左到右解释的,但是在解释I / O重定向之前设置了管道。 文件描述符(如1和2)是对打开的文件描述的引用。 操作2>&1使得文件描述符2(也称为stderr)指代与文件描述符1(也就是stdout当前指的是(参见dup2()open() )相同的打开文件描述。 操作>/dev/null然后更改文件描述符1,以便它指向/dev/null的打开文件描述,但不会改变文件描述符2引用的文件描述符1为原来指向 – 即管道。

或者通过使用交换stderr和stdout的输出: –

 command 3>&1 1>&2 2>&3 

这将创建一个新的文件描述符(3)并将其分配到1(stdout)的相同位置,然后将fd 1(stdout)分配给与fd 2(stderr)相同的位置,最后将fd 2(stderr)分配给相同的位置放置为fd 3(stdout)。 Stderr现在可以作为标准输出和旧stdout保存在stderr中。 也许是矫枉过正,但希望提供有关bash文件描述符的更多细节(每个进程有9个可用)。

在Bash中,你也可以使用进程替换重定向到一个子shell:

 command > >(stdlog pipe) 2> >(stderr pipe) 

对于手头的情况:

 command 2> >(grep 'something') >/dev/null 

结合最好的答案,如果你这样做:

command 2> >(grep -v something 1>&2)

…然后所有的stdout被保存为stdout 所有的stderr被保存为stderr,但是你不会在stderr中看到任何以字符串“something”开头的行。

这具有独特的优势,不会扭转或丢弃粗壮,也不会将它们压在一起,也不会使用任何临时文件。

如果你想一想“重定向”和“管道”到底发生了什么,想象的东西要容易得多。 bash中的重定向和管道做一件事情:修改进程文件描述符0,1和2指向的地方(参见/ proc / [pid] / fd / *)。

当一个管道或“|” 运算符存在于命令行中,首先要做的事情是bash创建一个fifo,并将左侧命令的FD 1指向这个fifo,并将右侧命令的FD 0指向同一个fifo。

接下来, 从左到右评估每一侧的重定向操作符,并且当描述符的重复发生时使用当前设置。 这一点很重要,因为由于先设置了管道,FD1(左侧)和FD0(右侧)已经改变了,它们通常已经被改变了,任何重复都会反映出这个事实。

因此,当你键入如下内容:

 command 2>&1 >/dev/null | grep 'something' 

这是发生了什么,为了:

  1. 一个管道(fifo)被创建。 “命令FD1”指向这个管道。 “grep FD0”也指向这个管道
  2. “命令FD2”指向“命令FD1”当前指向的地方(管道)
  3. “命令FD1”指向/ dev / null

所以,所有“命令”写入其FD 2(stderr)的输出将进入管道,并由另一侧的“grep”读取。 “命令”写入其FD 1(stdout)的所有输出都将转到/ dev / null。

相反,如果运行以下操作:

 command >/dev/null 2>&1 | grep 'something' 

以下是发生的事情:

  1. 一个管道被创建并且“命令FD 1”和“grep FD 0”被指向它
  2. “命令FD 1”指向/ dev / null
  3. 指令FD 2指向FD 1当前指向的位置(/ dev / null)

所以,从“命令”的所有stdout和stderr到/ dev / null。 没有任何东西进入管道,因此“grep”将关闭,而不在屏幕上显示任何东西。

另请注意,重定向(文件描述符)可以是只读(<),只写(>)或读写(<>)。

最后的笔记。 程序是否写入FD1或FD2,完全取决于程序员。 良好的编程习惯决定了错误消息应该到FD 2并且正常的输出到FD 1,但是你经常会发现混合这两者的草率编程或者忽略了这个约定。

你使用bash吗? 如果是这样:

 command >/dev/null |& grep "something" 

http://www.gnu.org/software/bash/manual/bashref.html#Pipelines

对于那些想要stdout和stderr永久重定向到文件,grep stderr,但保持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 

这会将command1 stderr重定向到command2 stdin,而将command1 stdout保留原样。

 exec 3>&1 command1 2>&1 >&3 3>&- | command2 3>&- exec 3>&- 

采自自民党

我尝试跟随,找到它的工作,

 command 1> /dev/null | grep 'something'