第一篇我们学习了Shell当中的变量和符号,接下来我们来学习一下Shell当中的语法。
语法无非是有几个点,条件判断,循环控制,以及面向过程最重要的一点——函数。
首先我们来看一下test和[,这两个是有关于条件测试的。
test命令和[的作用是一样的,都是用来判断条件是否成立。而对于条件的描述,就需要我们在上一节所说的关系运算符等
运算符 | 说明 |
---|---|
-eq | 判断是否相等 |
-ne | 判断是否不相等 |
-le | 判断前面的是否小于等于后面的 |
-lt | 判断前面的是否小于后面的 |
-ge | 判断前面的是否大于等于后面的 |
-ft | 判断前面的是否大于后面的 |
所以我们可以写一个例子:
test 5 -eq 3
echo $?
因为[和test是一样的,所以我们也可以使用[来进行判断。另外,为了让[好看点,所以Shell使用[XXX]来进行条件测试
[ 5 -le 34 ]
echo $?
这里特别需要注意的是[ ]它们算是命令,所以命令与参数之间一定要使用空格隔开,这样才能执行。
说完了测试,我们所具备的条件就成熟了,我们可以说分支控制了。
Shell当中的if…else和C当中的使用类似,只是在书写上有些差别。
例子:
read a
if [ a -gt 10 ] ; then
echo "hello"
fi
这就是标准的只有一个if的判断,我们加上else
read a
if [ a -gt 10 ] ; then
echo "hello"
else
echo "world"
fi
当然,还有if…elseif…else,书写和C有些区别。
read a
if [ $a -gt 10 ] ; then
echo "hello"
elif [ $a -eq 10 ] ; then
echo "wond"
else
echo "world"
fi
上面就是典型的if…elseif…else这种格式,注意书写格式!
read命令是用来读取字符串,然后进行操作。
还记得C语言当中的那个switch…case吗?在Shell当中,也提供了一个类似的——case。
read a
case $a in
'1')
echo hello
;;
'2')
echo world
;;
'3')
echo wond
;;
*)
echo ll
esac
这个就是整个case语句的样式,注意格式书写。这里的*其实就代表了default。
循环语句,Shell当中也需要说三种。
这就是简单的for循环的例子。
read n
sum=0
for(( i=0; i<=n; i++ ))
do
let sum+=i
done
echo sum
上面这个程序是计算0-n之间的整数求和的程序,这里需要注意的是,一个是do…done维护循环的循环体,然后是循环体内进行计算的时候要前面加上let。
Shell单独有一种for…in…的循环
arr=(456 789 132 65)
for i in ${arr[@]}
do
echo $i
done
上面的程序是for…in打印数组的程序,for…in使用更加方便,快捷。
read i
while [ $i -gt 0 ]
do
echo "hello world!"
done
do…done之间依然是循环体,然后其他就不需要多说了,和前面的一样。
Shell当中提供了一种until循环,这个until循环
read n
while [ $n -eq 0 ]
do
echo "hello world"
let n--
done
until就是当条件为真的时候跳出,条件为假的时候执行do…done循环体。
然后还需要说一下控制循环的continue和break, 这个用法和C语言当中的用法是一样的。
想要写死循环,我们一般使用while当中的两种结构来书写,一种是for do…done的结构,一种是while do…done的结构。
for(( ; ; ))
do
:
done
注意这里的:就是代表空行的意思,Shell当中的所有的空行都可以用:来进行处理。
while [ 1 -ne 2 ]
do
:
done
面向过程的语言最重要的就是函数了,当然,Shell当中也提供了函数。
一个函数我们需要关心的无非是三个东西,参数,返回值,函数体。
所以我们也就从这三个方面进行解决,就解决了函数的书写问题。
首先说函数的参数,函数参数我们使用$n的方式进行传参。
例如我调用fun函数 fun 1,那么我就可以在fun函数当中使用$1参数了。
function fun()
{
echo $1
}
fun helloworld
这样,一个简单的函数就调用完成了。这里的function就是进行函数定义的时候需要带上的。
这里的$1就表示第一个参数,后面的参数以此类推。
然后看返回值的问题,返回值来说函数有两种方式返回,一种是采用上面那种进行echo xxxx。另外的一种是采用return。但是注意return只能够返回的值必须小于256另外,在Shell函数内部进行定义变量的时候,此时的变量都是全局变量,所以你也可以采取变量进行返回,如果你想要把全局变量定义为局部的变量,那么就前面加上local。
read d
function fun()
{
n=$1
for(( i=0; ido
echo hello world!
done
}
fun d
首先Shell是支持调试的,所以我们可以通过调试来检查Shell出错在哪。
调试有三种方法,
第一种方法说的是在运行fib.sh的时候,我们采用bash -x a.sh
第二种方法说的是在脚本文件内部的shebang后面调试的参数。例如:
#! /bin/bash -x
要记住你使用第二种方法改了shebang以后,不要再使用bash的方式进行运行,否则无法调试。
第三种方式是在Shell脚本内部进行设定,使用set -x
和set +x
例如:
这种方法有一个好处是在这种情况下,可以进行调试一个Shell脚本当中自己关心的一部分就可以了。
Shell脚本,我们常用来做一些平时的操作,例如:
操作 | 说明 |
---|---|
命令>文件 | 把输出重定向到文件 |
命令<文件 | 把输入重定向到文件 |
命令>>文件 | 进行追加重定向到文件 |
A>&B | 把输出文件A和B合并 |
A<&B | 把输入文件A和B合并 |
<\ | 将开始标记tag和结束标记tag之间的内容作为输入 |
Here Document是Shell当中的一种特殊用法。
这里举一个例子来看一下这个使用。
cat << EOF
askjhfjakf
EOF
这样我就把EOF——EOF之间的内容当作参数传给cat作为参数。我们可以使用这种方法在Shell中来生成Makefile,这样就简单了许多。
/dev/null是一个特殊的文件,写入到这个文件中的内容都会被丢弃,如果你要读这个文件当中的内容,那么也是什么也都读取不到的。/dev/null文件非常有用,可以起到禁止输出的作用。
例如,你要进行屏蔽标准输出:
ls > /dev/null 1