在 shell 下区分 stdout 和 stderr 的两种思路
1.使用命名管道重定向。在一个终端中新建命名管道,将标准错误重定向到此管道文件;在另一个终端中读取管道输出:
- linjian@goslin:~/dev/outerr$ cat ./test1.sh
- #!/bin/bash
- while true; do
- echo "Input: "
- read FOO
- echo "I am in stdout, $FOO"
- echo "I am in stderr, $FOO" >&2
- done
- linjian@goslin:~/dev/outerr$ mkfifo mypipe
- linjian@goslin:~/dev/outerr$ ./test1.sh 2> ./mypipe
- Input:
- Hello World
- I am in stdout, Hello World
- Input:
- linjian@goslin:~/dev/outerr$ cat ./mypipe
- I am in stderr, Hello World
也可以使用 Emacs 等在同一屏内显示两个终端。
2.使用匿名管道处理标准输出。由于标准错误不会进入管道,因此不会被管道后面的程序处理。例如使用“tr”来改变标准输出的大小写。
- linjian@goslin:~/dev/outerr$ ./test1.sh | tr [a-z] [A-Z]
- INPUT:
- Hello World
- I am in stderr, Hello World
- I AM IN STDOUT, HELLO WORLD
- INPUT:
想要更明显一点的话,可以用 ANSI 颜色特性,自己写一个简单的过滤器:
- linjian@goslin:~/dev/outerr$ cat color.sh
- #!/bin/bash
- while true; do
- read FOO
- echo -e "\E[33;44m$FOO\E[37;40m"
- done
或者直接使用像 ansi-color 这样的现成工具。

5条评论 关于 “在 shell 下区分 stdout 和 stderr 的两种思路”
由 erhai 发表于2009-08-25
你好,有个问题想问你,在c语言中EOF值是什么意思,具体说一下,网上的答案不是很明白.
还有在linux中ctrl-d与ctrl-c的区别
由 Jian Lin 发表于2009-08-25
EOF 的定义请看 http://en.wikipedia.org/wiki/End-of-file ,在 C 库中表示文件读到了结尾。
Ctrl-D 发出的是终端接受的、表示输入结束的控制字。
Ctrl-C 发出的是 SIGINT 信号,由前台进程接受,默认的响应就是终止运行。
由 erhai 发表于2009-08-26
首先非常感谢你的帮助,我也是计算机专业的马上就大二了,以后有专业问题的话,希望你能够不吝赐教.
第一个问题我已经明白了(你平时都看的英文资料吧!!!但是怎么介绍上说自己英语学的不怎么明白呢???)
第二个问题中ctrl-c那个明白了,但是关于那个ctrl-d它不是发送的信号吗?只是发出二进制值吗?
还有一个关于编程方面的问题
平时的好多代码自己都能看懂(包括一些稍微复杂的),
但为什么等到自己写的时候就不知如何整理自己的思路来写呢?(指稍微复杂的)
再次表示感谢!!!
由 Jian Lin 发表于2009-08-26
Ctrl-D 不是信号。在终端下,Ctrl-A 到 Ctrl-Z 分别发出的是 ASCII 1 到 26 的字符。这些字符中有一部分是终端控制字,比如 4(Ctrl-D)代表传输结束。终端得到这个控制字之后,会让类似于 getchar() 之类的函数返回一个 -1 之类的代表 EOF 的值,目标程序中读到这个 EOF 值后可以做停止读写或退出之类的操作。
编程要多积累,多实践,阅读代码的时候带着自己的思考。
学术、科研英语的范围比较窄,句法简单,词汇规范。而且我平时也只涉及读写,听说训练有限。所以还是难以应付考试那种专门难为人的英语的。
由 erhai 发表于2009-08-27
非常感谢,我已经明白了,我写了一段代码测试了一下,好像linux终端只对ctrl-c,ctrl-\,ctrl-z这三个进行信号处理,结果分别是[2], [3], [20].按下ctrl-d后没反应的