企业🤖AI智能体构建引擎,智能编排和调试,一键部署,支持私有化部署方案 广告
总第4篇 在前面博文中我讲过了变量基础部分[《变量基本概念及其初始化》](http://blog.csdn.net/guodongxiaren/article/details/38402577)。我们知道假如我们有初始化一个变量a=hello,那么如果我们想打印它的值,我们需要使用echo $a。 但是除此之外还有很多特殊的变量,可供 $ 使用。本文讲到了$0 # * @ _ ? ! -这几个特殊变量的含义。 ## 脚本的参数 正如同C语言中有main(int argc,char **argv),Java中有main(String[]args)一样,Bash同样能对执行脚本时附加的参数做操作。 ### 引用脚本的参数n 看一个简单的脚本**test.sh**: ~~~ #!/bin/bash echo $0 $1 $2 $3 ~~~ 然后看一下我的屏幕输出情况。 ![](https://box.kancloud.cn/2016-02-19_56c6cdb26e516.jpg) 没错,和你想的一样。数字变量0,保存的是这个执行脚本的名称,其他的数字1到n保存该脚本运行时的第1到第n个参数。 如果没有脚本在运行,比如直接在终端中键入echo $0,那么显示的是shell的名称。 ### 参数的个数# 现在我们继续修改一下test.sh这个脚本 ~~~ #!/bin/bash echo "脚本$0的参数的个数为$#" echo "分别是:" echo $1 $2 $3 ~~~ 输出的结果是: ![](https://box.kancloud.cn/2016-02-19_56c6cdb282785.jpg) `#`号代表参数的个数,实际上在Bash中#代表个数的情况,并无只此一例,以后我们在讲*字符串操作*的时候还会见到。 ### 所有的参数*和@ 继续修改脚本 ~~~ #!/bin/bash echo "脚本$0的参数的个数为$#" echo "分别是:" echo $@ echo $* ~~~ 试试。 ![](https://box.kancloud.cn/2016-02-19_56c6cdb28fe00.jpg) 没错@,* 就是所有变量。从这里来看似乎两者没有差别。但是其实是不同的,通配符*将所有参数视作一个变量,而@则可以理解为所有参数的集合。 看一个长一点的脚本,star_at.sh(代表着star*和at@) 关于for循环,你可能还不理解,但是并没有关系,这里仅仅是简单的遍历。 ~~~ #!/bin/bash echo $* echo $@ echo "遍历不带引号的变量*" for i in $* do echo $i done echo "遍历带引号的变量*" for i in "$*" do echo $i done echo "遍历不带引号的变量@" for i in $@ do echo $i done echo "遍历带引号的变量@" for i in "$@" do echo $i done ~~~ ![](https://box.kancloud.cn/2016-02-19_56c6cdb29d64d.jpg) 看出来了没,当遍历的时候,可以发现,如果$@,$都没有被引号包围,那么两者没有差别。但是如果有了引号,则不同。可以发现$其实只是一个值而已。 ### 最后一个参数_ $_保存的是命令(或脚本)的最后一个参数。 ~~~ #!/bin/bash echo "脚本$0的参数的个数为$#" echo "分别是:" echo $@ echo "最后一个参数是$_" ~~~ 输出结果是: ![](https://box.kancloud.cn/2016-02-19_56c6cdb2b6313.jpg) ## 其他特殊变量 ### 退出码? 当我们执行完一个命令的时候,都可以用 echo $? 来查看命令的退出码 ***exit code***(或称返回码),从而判断命令是否正确执行。可以理解为命令的返回值(后面我们学到Bash函数的时候,也会用它来做返回值),但是与其他语言不同的是它只是一个固定的8位二进制数,也就是说它的范围是0-255。并没有其他语言中返回值那么丰富的功能。所以我个人喜欢称之为**码**而不是 值。(当然这不是重点) ![](https://box.kancloud.cn/2016-02-19_56c6cdb2c9597.jpg) 上面是个简单的例子,用which检查某个命令是否存在,通过返回值可以了解。0代表成功,非0代表不成功。这可能与其他语言的思想相悖,但是也可以理解,毕竟*成功的状态只有一个,而错误的情况却有许多种*,所以用正数来标记错误状态。 不过通常在脚本内部,我一般不会直接用到$?来判断一个命令的返回值,if [  ]就差不多了。 当前进程的PID $ echo $$可以打印当前进程的PID(PID是什么,我就不解释了)。继续修改test.sh,你只需要关注最后一句就可以了。 ~~~ #!/bin/bash echo "脚本$0的参数的个数为$#" echo "分别是:" echo $@ echo "最后一个参数是$_" echo "当前进程的PID为$$" ~~~ 输出结果是: ![](https://box.kancloud.cn/2016-02-19_56c6cdb2d90ee.jpg) ### 后台执行的最后一个命令的PID ! shell执行命令的时候有前台和后台的概念。一直和你交互的就是前台,但是有些命令会阻塞进程,导致你无法输入其他命令。比如在终端里打开了一个图形编辑器gedit或者火狐浏览器的时候。不过我们可以通过在命令后面加一个&,来把它丢到后台,比如** gedit &**,这样就不会阻塞前台进程,你可以继续输入其他命令。 我喜欢在终端启动浏览器,现在我们来试试$!,是不是可以查看它的PID。 ![](https://box.kancloud.cn/2016-02-19_56c6cdb2e8a4c.jpg) 关于 >/deb/null 2>&1这部分会在以后输入输出重定向的时候讲到。它的功能是把火狐的各种终端输出丢进垃圾桶,不在屏幕上显示。 ### 当前shell的默认选项 - ![](https://box.kancloud.cn/2016-02-19_56c6cdb309704.jpg) himBH是Bash的当然的默认选项,可以使用set -o打开某一选项,或者set +o来关闭某一选项。关于这几个选项的含义,超出本文叙述范围,![偷笑](https://box.kancloud.cn/2016-01-18_569ca4488de4a.gif) 超纲内容请同学们自行 - man bash - /-h - /-i - /-m - /-B - /-H 来查看![再见](https://box.kancloud.cn/2016-01-25_56a5a366e5bcb.gif) 本系列(玩转Bash脚本)更多文章,请访问:[http://blog.csdn.net/column/details/wanbash.html](http://blog.csdn.net/column/details/wanbash.html)