shell 语法总结

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

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

shell 的工作原理为:

接下来讲 shell 的语法

变量

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

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

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

命令代换

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

引号

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

条件语句

条件测试

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

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 表示判断条件是否为真,其语法形式如下:

a=10
if [ $a -gt 10 ]
then
    echo 'gt'
elif [ $a -lt 10 ]
then
    echo 'lt'
else
    echo 'eq'
fi

分支语句

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

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 循环有两种形式,如下:

sum=0
for i in {1..100}
do
    ((sum=$sum+$i))
done
echo $sum

或者

sum=0
for ((i=0;i<=100;++i))
do
    ((sum=$sum+$i))
done
echo $sum

while循环

sum=0
i=0
while [ $i -le 100 ]
do
    ((sum=$sum+$i))
    ((i++))
done
echo $sum

位置参数和特殊变量

shell中的特殊变量有

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

函数

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

它可以分解成:

:()
{
    :|:&amp;
};
:

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

调试

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

【完】