在使用STDOUT统一它之前,是否有任何方法在bash中通过过滤器管道STDERR?也就是说,我想要
STDOUT ────────────────┐
├─────> terminal/file/whatever
STDERR ── [ filter ] ──┘
而不是
STDOUT ────┐
├────[ filter ]───> terminal/file/whatever
STDERR ────┘
答案 0 :(得分:56)
这是一个以how to swap file descriptors in bash为模型的示例。 a.out的输出如下,没有'STDXXX:'前缀。
STDERR: stderr output
STDOUT: more regular
./a.out 3>&1 1>&2 2>&3 3>&- | sed 's/e/E/g'
more regular
stdErr output
从以上链接引用:
- 首先将stdout保存为& 3(& 1加入3)
- 接下来将stdout发送到stderr(& 2被骗到1)
- 将stderr发送到& 3(stdout)(& 3被骗到2)
- close& 3(& - 被骗入3)
醇>
答案 1 :(得分:20)
过程替换的天真使用似乎允许stderr
与stdout
分开过滤:
:; ( echo out ; echo err >&2 ) 2> >( sed s/^/e:/ >&2 )
out
e:err
请注意stderr
stderr
和stdout
stdout
上出现o
,我们可以通过将整个内容包装到另一个子shell并重定向到文件{{1}来看到}和e
( ( echo out ; echo err >&2 ) 2> >( sed s/^/e:/ >&2 ) ) 1>o 2>e
答案 2 :(得分:8)
我发现bash过程替换的使用更容易记住和使用,因为它几乎逐字地反映了原始意图。例如:
$ cat ./p
echo stdout
echo stderr >&2
$ ./p 2> >(sed -e 's/s/S/') | sed 's/t/T/'
sTdout
STderr
仅使用第一个sed命令作为stderr的过滤器,使用第二个sed命令修改连接的输出。
注意2>之后的空格>必须正确解析命令。
答案 3 :(得分:8)
$ cmd 2> >(stderr-filter >&2)
示例:
% cat /non-existant 2> >(tr o X >&2)
cat: /nXn-existant: NX such file Xr directXry
%
这将同时在bash和zsh中工作。如今,Bash几乎无处不在,但是,如果您确实确实需要针对POSIX sh
和sp_BlitzCache
的(非常讨厌)解决方案。
到目前为止,最简单的方法是通过see here重定向STDERR:
进程替换允许使用文件名引用进程的输入或输出。它采用
的形式>(list)
进程列表是异步运行的,其输入或输出显示为文件名。
所以用流程替换得到的是文件名。
就像您可以做的一样:
$ cmd 2> filename
你可以做
$ cmd 2> >(filter >&2)
>&2
重定向的filter
的STDOUT返回原始STDERR。
答案 4 :(得分:5)
Advanced Bash脚本编写指南的this page的最后一部分是“仅将stderr重定向到管道”。
#仅将stderr重定向到管道。
exec 3>&1 # Save current "value" of stdout. ls -l 2>&1 >&3 3>&- | grep bad 3>&- # Close fd 3 for 'grep' (but not 'ls'). # ^^^^ ^^^^ exec 3>&- # Now close it for the remainder of the script.
#Thanks,S.C。
这可能就是你想要的。如果没有,ABSG的其他部分应该能够帮助你,这非常好。
答案 5 :(得分:5)
$ cmd 2> >(stderr-filter >&2)
示例:
% cat /non-existant 2> >(tr o X >&2)
cat: /nXn-existant: NX such file Xr directXry
%
StackExchange网络上的许多答案都采用以下形式:
cat /non-existant 3>&1 1>&2 2>&3 3>&- | sed 's/e/E/g'
这是一个内置的假设:文件描述符3并未用于其他用途。
相反,请使用命名文件描述符,{ba,z}sh
将分配下一个可用的文件描述符> = 10:
cat /non-existant {tmp}>&1 1>&2 2>&$tmp {tmp}>&- | sed 's/e/E/g'
请注意,POSIX sh
不支持命名文件描述符。
上述内容的另一个问题是,如果不再次将STDOUT和STDERR交换回其原始值,则无法将该命令传递给其他命令。
要允许在POSIX sh
中继续管道传输(并且仍然假设未使用FD 3),请使用gets complicated:
(cmd 2>&1 >&3 3>&- | stderr-filter >&2 3>&-) 3>&1
因此,鉴于此假设和陈旧的语法,使用上面的TL; DR中显示的简单bash
/ zsh
语法并解释{{3 }}。
答案 6 :(得分:3)
看一下命名管道:
$ mkfifo err
$ cmd1 2>err |cat - err |cmd2