shell语法总结

<div id="MathJax_Message" style="display: none;"></div>

众所周知,Linux的精髓就在于其强大的命令行,命令行的作用就是与系统提供的命令或内核提供的系统调用进行交互,而shell就承担了这一任务。

Linux下常见的shell有ksh,csh,sh,tcsh,bash等,可在/etc/shells文件查看,这里不表。本文以bash为例。 <!--more-->

shell的工作原理为:

  • 等待用户输入命令
  • 当用户输入完成后,分析语句是否合法
  • 若合法,则fork一个新的进程。在子进程中exec用户所请求的程序,父进程wait子进程。
  • 处理完成后,再次等待用户输入命令

接下来讲shell的语法

变量

shell中变量分为本地变量和环境变量。可以通过export命令将一个本地变量更新为环境变量。unset可以删除一个变量。

本地变量不用定义,第一次使用时直接拿来用即可。例如val=10。之后需要取得该变量的值时,前面加一个$符号即可,例如echo $val

环境变量是形如name=val形式的字符串,可以通过printenv命令查看所有的环境变量。

命令代换

shell允许一个命令的输出成为另一个命令的一部分,即命令代换。例如echodate``,shell先执行一对反引号中的命令,并用其输出替换命令本身,再执行echo命令。反引号可以用$()替换。

引号

shell中的单引号和双引号都用来表示字符串的定界符,所不同的是单引号中所有字符都表示它本身的意义,\和回车符号。而双引号中

  • $加变量名仍然可以取变量的值
  • 反引号扔表示命令替换
  • \表示转义字符

条件语句

条件测试

条件测试有两种命令,test[,例如:

1
2
test $a -gt 10 && echo 'gt 10'
[ $a -gt 10 ] && echo 'gt'

可以看出,’[‘命令需要’]’来配对,并且他们与里面的语句之间必须要有一个空格。

gt是比较操作,意为大于(Greater Than),其他比较操作还有小于(Less Than,lt),等于(EQual,eq),大于等于(Greater or Equal,ge),小于等于(Less or Equal,le),不等于(Not Equal,ne)等。

if/then/else/elif/fi

if表示判断条件是否为真,其语法形式如下:

1
2
3
4
5
6
7
8
9
10
a=10
if [ $a -gt 10 ]
then
echo 'gt'
elif [ $a -lt 10 ]
then
echo 'lt'
else
echo 'eq'
fi

分支语句

shell中分支语句为case/esac,示例如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
a=10
case $a in
1)
echo 'a is 1'
;;
10)
echo 'a is 10'
;;
100)
echo 'a is 100'
;;
*)
echo 'a is other'
;;
esac

当a为1或10或100时,就会跳转到对应的语句上执行,然后遇到两个分号时跳出。星号代表通配符,类似于C语言中的default语句。

循环语句

for循环

for循环有两种形式,如下:

1
2
3
4
5
6
sum=0
for i in {1..100}
do
((sum=$sum+$i))
done
echo $sum

或者

1
2
3
4
5
6
sum=0
for ((i=0;i&lt;=100;++i))
do
((sum=$sum+$i))
done
echo $sum

while循环

1
2
3
4
5
6
7
8
sum=0
i=0
while [ $i -le 100 ]
do
((sum=$sum+$i))
((i++))
done
echo $sum

位置参数和特殊变量

shell中的特殊变量有

  • <span>$</span>0:相当于argv[0]
  • <span>$</span>1…:相当于argv[1]…
  • <span>$</span>@:表示参数列表,即<span>$</span>1,<span>$</span>2,…
  • <span>$</span>#:相当于argc-1
  • <span>$</span>?:表示上一条命令的退出码
  • <span>$</span><span>$</span>:表示当前shell的进程号

位置参数可以通过shift命令左移,若shift后面不跟数字,则默认为1

函数

函数定义和C语言差不多,只不过shell中函数没有参数和返回值。取而代之的是,参数继续用$1,$2来使用,返回值用return或echo命令返回。下面是一个著名的fork炸弹::(){ :|:&amp; };:

它可以分解成:

1
2
3
4
5
:()
{
:|:&amp;
};
:

其中:是函数名,括号代表是一个函数,一对花括号代表函数的起始和结束,在函数体里面递归调用本身并将输出通过管道传递给另一个该函数,并放入后台执行。所以该函数会以2<sup>n</sup>增长,造成系统无响应,只能重启。解决方法是通过ulimit命令限制一个用户最多可以创建的进程数。

调试

shell脚本的调试方法为在解释器语句后面加上-x,在执行时会打印出执行的每一条语句。

【完】