phi*_*294 2 io-redirection shell-script
我正在尝试stderr
在终端中将我的打印为红色。以下脚本在调试陷阱时将 重定向2
到自定义8
。
exec 9>&2
exec 8> >(
while IFS='' read -r line || [ -n "$line" ]; do
echo -e "${RED}${line}${COLORRESET}"
done
)
function undirect(){ exec 2>&9; } # reset to original 9 (==2)
function redirect(){ exec 2>&8; } # set to custom 8
trap "redirect;" DEBUG
PROMPT_COMMAND='undirect;'
Run Code Online (Sandbox Code Playgroud)
它来自here,有明确的解释。
似乎工作得很好,但是根本不会打印出非换行符终止的输入。再次引用作者的福音:
bash> echo -en "hi\n" 1>&2
hi <-- this is red
bash> echo -en "hi" 1>&2
bash> echo -en "hi" 1>&2
bash> echo -en "hi\n" 1>&2
hihihi <-- this is red
Run Code Online (Sandbox Code Playgroud)
我不明白为什么。非换行内容似乎以某种缓冲区结束。它甚至没有到达文件描述符8
,或者以某种方式不想立即打印出来。它去哪里?redirect
每次都被正确调用。此外,IFS=''
意味着没有分隔符,所以我不太明白为什么回显是按8
行发生的。
一个错误修正将不胜感激,我将引用的答案链接到这个问题。
正如吉尔斯所指出的,整个解决方案并不完美。我在读取、标准输入、进度条方面遇到问题,既不能su
也不能source
。并且经常出现重大问题,例如管道破裂和意外终端出口。如果有人通过我的链接到达这里,请考虑使用https://github.com/sickill/stderred代替,它好多了(还没有问题)(但是echo bla >&2
仍然是非红色并且相应的问题已关闭)
您确实获得了部分行输出,作为打印换行符的同一行的一部分。该行的部分在 内缓冲read
,这就是它的作用:
该读实用程序应当从标准输入读取一个单一的逻辑线
例如,这会<foobar>
在一秒钟后打印,而不是<foo><bar>
。
(echo -n foo ; sleep 1 ; echo bar) | (read x ; echo "<$x>")
Run Code Online (Sandbox Code Playgroud)
如果您想捕获比整行更小的部分的输入,您需要做一些其他的事情,例如使用 Perl。这将打印<foo><bar\n>
(在最后一个之前使用换行符>
,因为与 不同read
,Perl 不会特别处理最后的换行符。应该与着色无关。)
(echo -n foo ; sleep 1 ; echo bar) |
perl -e '$|=1; while(sysread STDIN,$a,9999) { print "<$a>"}'
Run Code Online (Sandbox Code Playgroud)
如果您在环境中导出了颜色 (RED
和COLORRESET
)的控制代码,您可以在 Perl 脚本中使用它们,如下所示:
perl -e '$|=1; while(sysread STDIN,$a,9999) {print "$ENV{RED}$a$ENV{COLORRESET}"}'
Run Code Online (Sandbox Code Playgroud)