SHELL脚本攻略(学习笔记)

时间:2020-12-10 15:39:07
1.6.1 重定向基础

最常见的标准输入(stdin)、标准输出(stdout)和标准错误输出(stderr)描述符分别是0、1和2,可以认为输出是打印在屏幕上的信息,没给出错误的就是标准输出,给出错误提示的是标准错误输出,虽然有些偏颇,但是易于理解。也可以自定义自己的描述符,不过好像没什么必要。

标准输入-->代号0-->使用<或<<符号,一般来说是将file的内容作为stdin。

标准输出-->代号1-->使用>或>>符号,可以将file内容或本来打印在屏幕的内容作为stdout。

标准错误输出-->代号2-->使用2>或2>>符号,将本应打印在屏幕的错误输出作为stderr。

判断是标准输出还是标准错误输出的方法是"echo $?"命令,返回0则是标准输出,返回非0则是标准错误输出。

注意到了吧,“?”其实是一个变量,代表上一次执行代码的回传指令,指令为0则表示是正确执行的,否则是错误执行。其实$自身也是一个变量,试试"echo $$",返回一个数字,这个数字是当前shell的PID,可以使用ps aux|grep $$查看。

更多的预定义变量请查看http://www.cnblogs.com/f-ck-need-u/p/5915268.html

<、>、2>实现的是覆盖功能,>>、2>>实现的是追加的功能,但是注意,标准输入没有追加的概念,<<表示的是此处生成文档的意思,关于此,看完下面cat和重定向的配合时就明白了。

[root@xuexi tmp]# echo 'Hello World!'>test.txt   çtest.txt可以不存在,会自动创建

[root@xuexi tmp]# cat test.txt

Hello World!

[root@xuexi tmp]# echo 'The Second Hello World!'>>test.txt   ç追加的方式

[root@xuexi tmp]# cat test.txt

Hello World!

The Second Hello World!  ç追加的内容

标准错误输出记录到文件中。

[root@xuexi tmp]# ls +

ls: cannot access +: No such file or directory

[root@xuexi tmp]# ls + 2>err.log  ç没有在屏幕上打印错误内容

[root@xuexi tmp]# cat err.log ç已经输入到了文件中去了

ls: cannot access +: No such file or directory

[root@xuexi tmp]# echo $?   ç查看$?

2

脚本常见2>&1和&>的符号,它表示将标准输出和标准错误输出都记录到同一个地方去。如常见的丢到垃圾桶/dev/null去,&> /dev/null。

[root@xuexi tmp]# cat ab* &>/dev/null

将stdout或stderr丢到/dev/null表示丢弃信息,反过来用,将/dev/null丢到某个文件则表示清空文件。

[root@xuexi tmp]# cat /dev/null > ab.sh

[root@xuexi tmp]# cat ab.sh

最后最重要的一点:在有重定向符号的语句中,命令执行之前已经将文件截断了。所以如果正在编辑一个文件并将编辑的结果重定向回这个文件将出现乱码,因为截断后就没有合适的内容用于编辑。

可以想象,有些时候直接使用“>”覆盖输出是具有危险性的。可以使用set -C来设置如果输出重定向文件已经存在(而不是重定向文件不为空)则不覆盖。使用set +C来取消set -C的效果。如果在设置了set -C时仍然想强制覆盖,可以使用“>|”代替“>”来重定向输出。同理错误输出也有此特性。

[root@xuexi tmp]# set -C

[root@xuexi tmp]# cat flip >ttt.txt

-bash: ttt.txt: cannot overwrite existing file

[root@xuexi tmp]# cat flip >| ttt.txt

[root@xuexi tmp]# set +C

1.6.2 cat和重定向配合

配合cat使用一次性分行输入内容到文件中。

[root@xuexi tmp]# cat <<eof>log.txt   ç追加的方式输入到log.txt

> this is stdin character

> eof

也可以使用下面的方法,是一样的。

[root@xuexi tmp]# cat >log1.txt <<eof  ç追加的方式输入到log1.txt

> this is stdin character first!

> eof

是否注意到异同点?一方面eof都必须使用<<eof,否则不会有继续输出的提示,另一方面配对eof包括中间的所有内容都作为cat的stdin,最后所有的cat内容作为stdout输入到log.txt。

下面的例子可以说明<<eof配对中的内容是cat的stdin。这也说明了使用<eof将不会有输出机会作为stdin,直接就用空字符覆盖了。

[root@xuexi tmp]# cat <<eof

> abc.com

> eof

abc.com

[root@xuexi tmp]# cat <eof   ç不给输入内容的机会

[root@xuexi tmp]#

[root@xuexi tmp]# cat <eof>log2.txt && cat log2.txt   ç将创建一个空文件

[root@xuexi tmp]#

1.6.3 tee双重定向

可以使用tee双重定向。一般情况下,重定向都是将信息输入到文件中,这时候就不会在屏幕上打印或将信息通过管道传给其他功能了。使用tee就可以。如图。SHELL脚本攻略(学习笔记)

例如下面的代码,将a开头的文件内容全部拼接后保存到b.log,同时把副本交给后面的的cat,使用这个cat又将内容保存到了x.log。其中“-”代表前面的stdin。

[root@xuexi tmp]# cat a* | tee b.log | cat - >x.log

还可以:

[root@xuexi tmp]# cat a* | tee b.log | cat

#!/bin/bash

#文件名:abc.sh

printf "%-s\t %-s\t %s\n" No Name Mark

printf "%-s\t %-s\t %4.2f\n" 1 Sarath 80.34

printf "%-s\t %-s\t %4.2f\n" 2 James 90.998

printf "%-s\t %-s\t %4.2f\n" 3 Jeff 77.564

tee默认会使用覆盖的方式保存到文件,可以使用-a选项来追加到文件。如:

[root@xuexi tmp]# cat a* | tee -a b.log | cat

现在就可以在使用cat和重定向创建文件或写入内容到文件的同时又可以在屏幕上显示一份。

[root@xuexi tmp]# cat <<eof | tee ttt.txt

> x y

> z 1

> eof

x y

z 1

[root@xuexi tmp]# cat ttt.txt

x y

z 1

1.6.4 重定向的表示符号

stdin可以使用“-”或者/dev/stdin来表示。

stdout可以使用/dev/stdout来表示。

stderr可以使用/dev/stderr来表示。