linux搜索过滤器,关于linux:通过过滤器仅管道STDERR

在使用STDOUT统一它之前,有没有办法在bash中通过过滤器管道STDERR? 那就是我想要的

STDOUT ────────────────┐

├─────> terminal/file/whatever

STDERR ── [ filter ] ──┘

而不是

STDOUT ────┐

├────[ filter ]───> terminal/file/whatever

STDERR ────┘

另请参见如何管道stderr,而不是stdout?。

这是一个例子,模仿如何在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

引用上面的链接:

First save stdout as &3 (&1 is duped into 3)

Next send stdout to stderr (&2 is duped into 1)

Send stderr to &3 (stdout) (&3 is duped into 2)

close &3 (&- is duped into 3)

附加参考:BashFAQ / 047

这适用于任何POSIX shell,而不仅仅是Bash。

它对我不起作用。最后,我使用3>&2 2>&1 1>&3-。

注意:这假设FD 3未使用,并且不撤消文件描述符1和2的交换,因此您无法继续将此管道传递给另一个命令。有关更多详细信息和解决方法,请参阅此答案。对于{ba,z} sh更清晰的语法,请参阅此答案。

过程替换的天真使用似乎允许从stdout分别过滤stderr:

:; ( echo out ; echo err >&2 ) 2> >( sed s/^/e:/ >&2 )

out

e:err

请注意stderr出现在stderr上,stdout出现在stdout上,我们可以通过将整个事物包装在另一个子shell中并重定向到文件o和e来看到

( ( echo out ; echo err >&2 ) 2> >( sed s/^/e:/ >&2 ) ) 1>o 2>e

为什么 :;一开始?我没有试过魔法线,似乎没有什么区别。

有些人使用$作为命令提示符。然后他们经常编写shell示例:$ cat /var/log/syslog | fgrep ...。但是,由于$,此行不可复制。 :;看起来像一个提示,但基本上是一个shell no-op;这样您就可以安全地选择并粘贴整条生产线。

好的,但你可以省略:;这条线也可以复制 - 给我:;看起来不像一个提示,它没有使示例更清晰(从输出中分离命令)但令人困惑。虽然我理解你的观点,但我们不讨论语法/惯例。

TL; DR:

$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的解决方案,那么请看这里。

说明

到目前为止,最简单的方法是通过进程替换重定向STDERR:

Process substitution allows a process’s input or output to be referred to using a filename. It takes the form of

>(list)

The process list is run asynchronously, and its input or output appears as a filename.

所以你用过程替换得到的是一个文件名。

就像你能做的那样:

$cmd 2> filename

你可以做

$cmd 2> >(filter >&2)

>&2重定向的filter的STDOUT回到原来的STDERR。

我发现使用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>之后的空格对于正确解析命令是必需的。

TL; DR:(bash和zsh)

$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不是它使用的)它变得复杂:

(cmd 2>&1 >&3 3>&- | stderr-filter >&2 3>&-) 3>&1

所以,考虑到这个假设和粗略的语法,你可能会更好地使用TL中显示的更简单的bash / zsh语法;上面的DR,并在此解释。

Advanced Bash Scripting Guide的这一页的最后一部分是"仅将stderr重定向到管道"。

# Redirecting only stderr to a pipe.

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的其他部分应该能够帮助你,这是非常好的。

我们有点犹豫是否建议将ABSG作为参考,因为它混合了文档,处方和意见,而没有明确区分差异。有些部分也有可疑的内容,虽然你链接到的那个似乎很好。

看一下命名管道:

$ mkfifo err

$ cmd1 2>err |cat - err |cmd2

不会cat - err打破stdout和stderr的穿插?

@Martin - 这取决于。如果cmd1,cat或cmd2缓冲输出,那么您可以看到输出不按顺序。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值