shell程序设计入门(二)
导语
shell语法
变量
shell变量和C语言的标识符命名的要求类似,在shell中,可以在变量名前加$访问其内容,然后可以用echo输出它
与echo对应的是read,它用来把用户的输入赋给变量,需要注意的事,脚本文件中参数以空白字符分割,如果一个参数包括多个空白符,就需要用引号引起来,并且单引号和双引号的操作方式是不一样的
引号
如果把$变量表达式放在双引号里,程序执行到该行会把变量替换成应有的值,如果放在单引号里就不会发生替换现象,下面是一个简单的示例程序
#!/bin/sh
string="This is a test"
echo $string
echo "$string"
echo '$string'
echo \$string
echo Please input
read string
echo '$string' now is $string
exit 0
通过这个程序可以看到单双引号以及echo还有read的使用和区别
环境变量
Linux系统的环境变量和Window其实类似,都是设定好的变量,将它们和用户在脚本中定义的区分开,它们一般是大写,书上给出的常用环境变量如下
参数变量
脚本在调用的时候是可以提供参数的,即使没有传递参数,环境变量依然存在,只不过它们的值为0,书上给出的参数变量如下
下面是一个简单的展示脚本相关变量的程序
var="Test"
echo $var
echo "程序$0正在运行$"
echo "第二个参数是$2"
echo "第一个参数是$1"
echo "参数列表是$*"
echo "用户的主目录是$HOME"
echo "请输入变量的新值"
read var
echo $var
echo "程序允许完成"
exit 0
运行的结果如下
条件
shell里的test/[ 更像是为了完善if判断而衍生的结构,并且由于test这个单词十分常用,甚至很多程序的名字就有,因此用[来搭配if更为常见,具体的字符串比较、算术比较和文件条件测试在使用的时候查阅即可,这里不多赘述
test和[的用法如下
test -f <filename>
[-f <filename>]
与if 搭配的示例如下
if test -f show_var
then
...
fi
#等价于
if [ -f show_var ]
then
...
fi
#等价于
if [ -f show_var ]; then
...
fi
书上给出了一个能够展现对应功能的脚本
if [ -f /bin/bash ]; then
echo "文件/bin/bash存在"
fi
if [ -d /bin/bash ]; then
echo "/bin/bash是一个目录"
else
echo "/bin/bash不是一个目录"
fi
该脚本的目的是检测/bin/bash是否是文件,以及是否是脚本,执行的结果如下
控制结构
if else
与C语言类似,shell也是用if else语句来实现逻辑上的判断和控制的,不同的是shell的if else更复杂一些,具体用法如下
if condition
then
statements
elif condition
then
statements
else
statemens
fi
这里直接给出书上的参考脚本并解释
c#!/bin/sh
echo "Is it moring? Please answer yes or no"
read timeofday
if [ $timeofday = "yes" ]#探讨这里加不加""
then
echo "Good morning"
elif [ $timeofday = "no" ]#同上
then
echo "Good afternoon"
else
echo "Can't recognized"
exit 1
fi
exit 0
结果如下
当然,这里的程序采用的是书上的第二个版本,它的问题是如果在输入的时候直接打回车,会导致timeofday变量没有接受到任何值变为空,于是判断语句的左边便缺失,判断语句无法执行
在shell当中,空和空句并不是一个东西,为了改善这个情况,需要吧$timeofday加上双引号,这样在判断的时候判断语句左边就是空句,就可以进行判断了
循环
for
shell中for的用法很简单,和python或者C++11有点像
for var in values
do
statements
done
与其他高级程序设计语言不同的是,这里的values是一个列表,里面通常是一些字符串(文件名或参数名
以下是一个使用通配符匹配的简单脚本,它负责找到当前目录下所有f开头的文件并打印它们的名字
for file in $(ls f*); do
echo $file
done
exit 0
执行的结果如下
while
while的用法也很简单,它一般用于不知道循环的次数或者持续寻找的情况
while condition; do
statements
done
以下是书上给出的一个判断密码的简单例子
echo "请输入密码"
read password
while [ "$password" != "password" ]; do
echo "请重试"
read password
done
echo "密码正确"
exit 0
运行结果如下
until
until是C语言没有的关键字,在shell中它与while条件反过来了,也就是循环执行到条件为真,while是循环执行到条件为假,一般来说,如果循环至少执行一次就用while,否则就用until
until condition
do
statements
done
这里给出上一节while程序的until版本
echo "Enter password"
read input
until [ "$input" = "password" ];do
echo "wrong password"
read input
done
exit 0
运行的结果如下
case
shell中case的用法比较复杂,和C语言的完全不一样,并且花样繁多,例如允许合并匹配、执行多条语句等
这里直接给出书上的最优程序及其运行结果
echo "Is it morning? Please answer yes or no"
read timeofday
case "$timeofday" in
yes | y | Yes |YES )
echo "Good Morning"
echo "Up bright and early this morning"
;;
[nN]*)
echo "Good Afternoon"
;;
*)
echo "Sorry, answer not recognized"
echo "Please answer yes or no"
exit 1
;;
esac
exit 0
AND和OR
AND
shell里的and(即&&)和C语言中的&&意思并不一样,它的作用是检查前一条命令的返回值,具体来说
order1 && order2 && order3......
这样的一条shell命令,会从左到右依次执行,如果当前执行的命令返回为true,下一条命令才能执行,否则就停止,可以理解为串联,中间一旦断了,后面都接不上
OR
shell的or(||)和C语言中的||意思也是不一样的,它和&&相反
order1 || order2 || order3......
该shell指令从左到右依次执行,直到执行到第一个返回true的命令或执行完所有命令为止,换句话说,当一条命令的返回值为false,它的下一条命令才能执行,正好和&&相反
函数
作为编程语言,shell同样可以构造函数并提供调用,调用的格式如下,和C语言很像
funciton_name()
{
statements
}
和C语言一样,shell编程中也会遇到局部变量和全局变量的问题,书上给出了一个相关的脚本如下
#!/bin/sh
sample_text="全局变量"
foo()
{
local sample_text="局部变量"
echo "函数foo正在运行"
echo $sample_text
}
echo "以下为sample_text在函数执行前的值"
echo $sample_text
foo
echo "以下为sample_txt在函数执行后的值"
echo $sample_text
exit 0
下面是运行结果,可以看到,在函数体内是以局部变量优先的
在此基础上,shell脚本中的函数可以调用脚本的参数作为函数的参数来使用,书上的例子如下
#!/bin/sh
yes_or_no(){
echo "Is your name $* ?"
while true
do
echo -n "Enter yes or no: "
read x
case "$x" in
y | yes ) return 0;;
n | no ) return 1;;
* ) echo "Answer yes or no"
esac
done
}
echo "Original parameters are $*"
if yes_or_no "$1"
then
echo "Hi $1, nice name"
else
echo "Never mind"
fi
exit 0
执行的结果如下,可以看到输入的xxx从脚本的参数变成了函数的参数并进入了函数
总结
由于该章篇幅过多,因此本篇只选择了语法中的变量到函数的部分,需要注意的是shell和C语言有很多相似之处,使用的时候注意理解和区分
参考文献
- 《Linux程序设计(第4版)》