Shell Scripts语法
时间:2010-10-30 来源:osullishuai80
Shell脚本类似于C语言,它也有固定的语言格式.简而言之,Shell脚本就像早期DOS年代的批处理文件(.bat),最贱的功能就是将许多命令写在一起,让用户很轻松的就能执行一个文件的Shell脚本,就能够一次执行多个命令.
(1)Shell脚本第一行的格式
#!/bin/sh
符号#!用来指定该脚本文件的解析程序,这里使用的是bin目录下的sh解析器.当编辑好脚本后,如果要执行该脚本,还必须使其具有可执行属性,即:
chmod + x filename
这样,该Shell脚本便可以执行了.如果该Shell脚本没有执行权限,如
chmod - x filename
此时运行该脚本时,系统提示: bash:./hello.sh:Permission denied
(2)Shell中的注释
在进行Shell编程时,以#开头的句子表示注释,直到这一行结束.如果使用了注释,即使相当长时间内没有使用该脚本,也能在很短的时间内明白该脚本的作用及工作原理.
(3)使Shell脚本中断的命令
可以使用exit命令来使程序中断,并给系统回传一个数值.
比如:
#!/bin/bash
echo "hello embeded! \n"
exit 0
系统打印出"hello embeded!"后换行.当执行到exit 0时就离开了脚本,并且给系统回传一个0.
(4)执行Shell脚本的命令
例如:Shell脚本名为hello.sh
<1>执行方法1: #./hello.sh
<2>执行方法2: #sh hello.sh
(5)Shell中的变量
在Shell脚本中,变量有两种,一种是用户自定义变量,另一种是系统默认变量.
1、用户自定义变量
在Shell编程中,所有的变量都由字符串组成,并且不需要预先对变量进行声明,即不需要事先声明变量的类型,如s1.也可以这样来理解,在Shell编程中,它支持的唯一类型的变量就是字符串.
例程1:
Shell脚本:mythirdscript.sh
#!/bin/sh
num=2
echo "this is the $numnd"
执行结果:
[root@localhost lishuai]# ./mythirdscript.sh
this is the
执行结果并不会打印出"this is the 2nd".可以使用花括号来告诉Shell,用户需要打印出变量num的值.
比如: echo "this is the ${num}nd"
执行结果:
this is the 2nd
例程2:数值运算
#/bin/bash
echo "input your first number"
read num1
echo "input your second number"
read num2
total=$(($num1*$num2))
echo "total=$total"
注意数学运算的这种写法: var=$(()) #两个括号或declare -i var,这样声明了var是一整型数.
Attention!!!
<1>自定义变量赋值时,"="左右两边都不能有空格.
<2>BASH中的语句结尾不需要分号.
<3>若变量内容由用户决定,可以使用"read"命令从终端键盘获取用户的输入值.
比如: #read -p "Please input your name" name
这样,用户输入的内容便保存在变量name中了.
2、系统默认的变量
<1> $# 传入脚本的命令行参数个数
<2> $* 所有命令行参数值,在各个参数值之间留有空格
<3> $0 命令本身(shell文件名)
<4> $1 第一个命令行参数
<5> $2 第二个命令行参数
Shell脚本:myforthscript.sh
#!/bin/sh
echo "number of vars:"$#
echo "values of vars:"$*
[ -n "$s1" ] && echo "value of var1:"$1
[ -n "$s2" ] && echo "value of var2:"$2
[ -n "$s3" ] && echo "value of var3:"$3
[ -n "$s4" ] && echo "value of var4:"$4
执行结果:
[root@localhost lishuai]# ./myforthscript.sh 1 2 3 4
number of vars:4
values of vars:1 2 3 4
value of var1:1
value of var2:2
value of var3:3
value of var4:4
Attention!!!
Shell脚本的局部变量
在C语言中有局部变量之说,在Shell脚本中同样有局部变量.在变量首次被赋值时加上local关键字可以声明一个局部变量.
Shell脚本:myfifthscript.sh
#!/bin/sh
hello="var1"
echo $hello
function func1 #使用关键字function定义一函数,函数名为func1
{
local hello="var2"
echo $hello
}
func1
echo $hello
执行结果:
[root@localhost lishuai]# ./myfifthscript.sh
var1
var2
var1
若将函数func1内的关键字local去掉,则执行结果为:
var1
var2
var2
(6)Shell中的判断条件
在Shell脚本中,要检测系统上某些文件或相关属性,可以使用test命令.比如,要检查/home/lishuai是否存在,可以这样来编写一脚本或命令.
#!/bin/bash
test -e /home/lishuai && echo "exit" || echo "not exit"
1.符号"&&"紧接在条件判断语句的后面,表示如果条件为真,则执行"&&"后面的语句.
2.符号"||"紧接在条件判断语句的后面,表示如果条件为假,则执行"||"后面的语句.
Shell中的测试标志
(1)某个文件名的"类型"检测(存在与否),如test -e filename
<1> -e 该文件名是否存在
<2> -f 该文件是否普通文件(-)
<3> -d 该文件是否一个目录(d)
<4> -b 该文件是否为一个块设备文件
<5> -c 该文件是否为一个字符设备文件
<6> -L 该文件是否为一个链接文件
在Linux系统中,"-"表示普通文件,"d"表示目录文件,"c"表示设备文件.
(2)文件的权限检测,如test -r filename
<1> -r 检测文件名对当前用户是否具有"可读"权限
<2> -w 检测文件名对当前用户是否具有"可写"权限
<3> -x 检测文件名对当前用户是否具有"可执行"权限
<4> -s 文件大小不为0
(3)两个整数之间的判断,如test n1 -eq n2
比较操作 整数操作 字符串操作
相同 -eq =
不同 -ne !=
大于 -gt >
小于 -lt >
大于或等于 -ge
小于或等于 -le
为空 -z
不为空 -n
例程:
比较整数a和b是否相等 if [ $a = $b ] (也可用eq)
判断整数a是否大于整数b if [ $a -gt $b ]
比较字符串a和b是否相等 if [ $a = $b ]
判断字符串a是否为空 if [ -z $a ]
判断整数变量a是否大于b if [ $a -gt $b ]
(4)多重条件判断,如test -r filename -a -x filename
<1> -a 两个条件同时成立,如test -r file -a -x file,则file同时具有r与x权限时返回true
<2> -o 两个条件任何一个成立,如test -r file -o -x file,则file具有r或x权限时返回true
<3> ! 条件求反,如test ! -x file,则file不具备x权限时返回true
(7)判断符号[]
除了test外,还可以使用判断符号[]来进行数据的判断.其中,中括号[]的使用方法与test几乎完全一致,只是中括号多用在条件判断语句if...then...fi中.
Attention!!!
判断符号[]中每个组件中间都要用空格来分隔,比如:
#name="lishuai"
# [ "$name" == "lishuai" ]
1.第一个方括号的左右两边分别有一个空格,第二个方括号的左右两边也分别有一个空格,符号"=="与两边的组件之间也各有一个空格.
2.中括号[]内的变量最好用双引号来设置.
3.中括号[]内的常量最好用双引号或单引号来设置.
4.在Shell脚本语言中,"=="用于判断逻辑表达式,是"比较";"="用于给变量设置内容,是"设置".
(8)条件判断(if...then...语句)
Attention!!!
在Shell脚本中,&&和||的含义不同.
(1) &&表示AND
(2) ||表示or
条件判断if...then...语句是Shell脚本语言中逻辑控制语言,它有三种常用写法:
(1)第一种格式:类似于C语言的if语句,只需要一个fi表示if语句的结束.
if [ 条件判断表达式 ]; then
#当条件判断表达式成立时,可以执行的命令
fi
(2)第二种格式:类似于C语言的if...else语句,只需要一个fi表示if语句的结束
if [ 条件表达式 ]; then
#当条件判断表达式成立时,可以执行的命令
else
#当条件判断表达式不成立时,可以执行的命令
fi
(3)第三种格式:类似于C语言的if...else if...else...
if [ 条件表达式1 ]; then
#当条件表达式1成立时,可以执行的命令
elif [ 条件表达式2 ]; then
#当条件表达式2成立时,可以执行的命令
else
#当条件表达式1和2均不成立时,可以执行的命令
fi (9)条件判断(case...esac语句)
这种条件判断类似于C语言中的switch...case...语句,其格式为:
case $变量名 in
"第一个变量内容")
程序段
;;
"第二个变量内容")
程序段
;;
*)
不包含第一个变量内容与第二个变量内容的其它程序执行段
exit 1
;;
esac
Attenton!!!
(1)case语句最后必须以esac为结尾.
(2)每一个变量内容的程序段最后都需要两个分号来表示该程序段的结束.
(3)最后的"*"作用类似于C语言中的default.
(10)函数在Shell中的应用
函数在Shell脚本中可以简化很多程序代码.在Shell脚本中,函数必须先定义再调用,且必须在程序的最前面来定义,这样才能在执行时找到可用的程序段.它有固定的定义格式:
function 函数名() {
程序段
}
Attention!!!
函数两边的大括号不能在同一行.
(11)循环(while...do...done、until...do...done)
两种循环的区别:while是为真时执行,until是为假时执行.
(1)循环while...do...done的格式
当condition条件成立时,就进行循环,直到condition的条件不成立才停止.
while [ condition ]
do
程序段
done
(2)循环until...do...done的格式
当condition条件成立时就终止循环,否则就持续执行循环的程序段.
until [ condition ]
do
程序段
done (12)循环(for...do...done)
for循环结构与C语言中有所不同,在BASH中for循环有两种基本结构:
基本结构1:
for (( 初始值; 限制值; 执行步长 ))
do
程序段
done
Attention!!!
<1>这种写法主要用于数值运算.
<2>从上面的for格式可以看出,各个组件之间分别用空格分隔.其实也可以不用这些空格,但建议使用.
基本结构2:
for var in con1 con2 con3 ...
do
程序段
done
Attention!!!
<1>$var是循环控制变量,[list]是var需要遍历的一个集合,do/done对包含了循环体,相当于C语言中的一对大括号.另外,如果do和for被写在同一行,必须在do前面加上";",
如 for $var in [list];do
<2>for循环语句执行过程:
将[list]中的每一个值赋给变量$var,然后执行程序段的操作.
第1次循环时,$var的内容是con1
第2次循环时,$var的内容是con2
第3次循环时,$var的内容是con3
第4次循环时,... ...
<3>注意,在for所在的那一行,变量day是没有加"$"符号的,而在循环体内,echo所在行变量day必须加上"$"符号.这是因为在for所在的那一行是对变量day的赋值,而不是引用.在Linux中,只有对变量的引用时才加上"$"符号. (13)Shell脚本的追踪与调试
脚本在执行之前就怕出问题.Linux提供了不需要通过直接执行该脚本就判断是否有问题.
[root@localhost lishuai]# sh [-nvx] scripts.sh
参数:
-n 不执行脚本,仅检查语法问题
-v 在脚本执行前,先将脚本的内容输出到屏幕上
-x 将使用的脚本内容显示到屏幕上,这个参数最有用.
比如:有一脚本文件test.sh,在运行该脚本前害怕出问题,可以使用Linux提供的途径来检查该脚本是否有问题.
[root@localhost lishuai]# sh -x test.sh
-x参数可以在执行前列出所有要执行的程序段.如果是程序段,则输出时最前面会加上"+"符号,表示它是程序段.
Attention!!!
Linux中有大量的脚本文件,若不直到该脚本的功能,可以使用vim编辑器打开该脚本文件,通过系统对它的描述(description)就可以明白了.
#!/bin/sh
符号#!用来指定该脚本文件的解析程序,这里使用的是bin目录下的sh解析器.当编辑好脚本后,如果要执行该脚本,还必须使其具有可执行属性,即:
chmod + x filename
这样,该Shell脚本便可以执行了.如果该Shell脚本没有执行权限,如
chmod - x filename
此时运行该脚本时,系统提示: bash:./hello.sh:Permission denied
(2)Shell中的注释
在进行Shell编程时,以#开头的句子表示注释,直到这一行结束.如果使用了注释,即使相当长时间内没有使用该脚本,也能在很短的时间内明白该脚本的作用及工作原理.
(3)使Shell脚本中断的命令
可以使用exit命令来使程序中断,并给系统回传一个数值.
比如:
#!/bin/bash
echo "hello embeded! \n"
exit 0
系统打印出"hello embeded!"后换行.当执行到exit 0时就离开了脚本,并且给系统回传一个0.
(4)执行Shell脚本的命令
例如:Shell脚本名为hello.sh
<1>执行方法1: #./hello.sh
<2>执行方法2: #sh hello.sh
(5)Shell中的变量
在Shell脚本中,变量有两种,一种是用户自定义变量,另一种是系统默认变量.
1、用户自定义变量
在Shell编程中,所有的变量都由字符串组成,并且不需要预先对变量进行声明,即不需要事先声明变量的类型,如s1.也可以这样来理解,在Shell编程中,它支持的唯一类型的变量就是字符串.
例程1:
Shell脚本:mythirdscript.sh
#!/bin/sh
num=2
echo "this is the $numnd"
执行结果:
[root@localhost lishuai]# ./mythirdscript.sh
this is the
执行结果并不会打印出"this is the 2nd".可以使用花括号来告诉Shell,用户需要打印出变量num的值.
比如: echo "this is the ${num}nd"
执行结果:
this is the 2nd
例程2:数值运算
#/bin/bash
echo "input your first number"
read num1
echo "input your second number"
read num2
total=$(($num1*$num2))
echo "total=$total"
注意数学运算的这种写法: var=$(()) #两个括号或declare -i var,这样声明了var是一整型数.
Attention!!!
<1>自定义变量赋值时,"="左右两边都不能有空格.
<2>BASH中的语句结尾不需要分号.
<3>若变量内容由用户决定,可以使用"read"命令从终端键盘获取用户的输入值.
比如: #read -p "Please input your name" name
这样,用户输入的内容便保存在变量name中了.
2、系统默认的变量
<1> $# 传入脚本的命令行参数个数
<2> $* 所有命令行参数值,在各个参数值之间留有空格
<3> $0 命令本身(shell文件名)
<4> $1 第一个命令行参数
<5> $2 第二个命令行参数
Shell脚本:myforthscript.sh
#!/bin/sh
echo "number of vars:"$#
echo "values of vars:"$*
[ -n "$s1" ] && echo "value of var1:"$1
[ -n "$s2" ] && echo "value of var2:"$2
[ -n "$s3" ] && echo "value of var3:"$3
[ -n "$s4" ] && echo "value of var4:"$4
执行结果:
[root@localhost lishuai]# ./myforthscript.sh 1 2 3 4
number of vars:4
values of vars:1 2 3 4
value of var1:1
value of var2:2
value of var3:3
value of var4:4
Attention!!!
Shell脚本的局部变量
在C语言中有局部变量之说,在Shell脚本中同样有局部变量.在变量首次被赋值时加上local关键字可以声明一个局部变量.
Shell脚本:myfifthscript.sh
#!/bin/sh
hello="var1"
echo $hello
function func1 #使用关键字function定义一函数,函数名为func1
{
local hello="var2"
echo $hello
}
func1
echo $hello
执行结果:
[root@localhost lishuai]# ./myfifthscript.sh
var1
var2
var1
若将函数func1内的关键字local去掉,则执行结果为:
var1
var2
var2
(6)Shell中的判断条件
在Shell脚本中,要检测系统上某些文件或相关属性,可以使用test命令.比如,要检查/home/lishuai是否存在,可以这样来编写一脚本或命令.
#!/bin/bash
test -e /home/lishuai && echo "exit" || echo "not exit"
1.符号"&&"紧接在条件判断语句的后面,表示如果条件为真,则执行"&&"后面的语句.
2.符号"||"紧接在条件判断语句的后面,表示如果条件为假,则执行"||"后面的语句.
Shell中的测试标志
(1)某个文件名的"类型"检测(存在与否),如test -e filename
<1> -e 该文件名是否存在
<2> -f 该文件是否普通文件(-)
<3> -d 该文件是否一个目录(d)
<4> -b 该文件是否为一个块设备文件
<5> -c 该文件是否为一个字符设备文件
<6> -L 该文件是否为一个链接文件
在Linux系统中,"-"表示普通文件,"d"表示目录文件,"c"表示设备文件.
(2)文件的权限检测,如test -r filename
<1> -r 检测文件名对当前用户是否具有"可读"权限
<2> -w 检测文件名对当前用户是否具有"可写"权限
<3> -x 检测文件名对当前用户是否具有"可执行"权限
<4> -s 文件大小不为0
(3)两个整数之间的判断,如test n1 -eq n2
比较操作 整数操作 字符串操作
相同 -eq =
不同 -ne !=
大于 -gt >
小于 -lt >
大于或等于 -ge
小于或等于 -le
为空 -z
不为空 -n
例程:
比较整数a和b是否相等 if [ $a = $b ] (也可用eq)
判断整数a是否大于整数b if [ $a -gt $b ]
比较字符串a和b是否相等 if [ $a = $b ]
判断字符串a是否为空 if [ -z $a ]
判断整数变量a是否大于b if [ $a -gt $b ]
(4)多重条件判断,如test -r filename -a -x filename
<1> -a 两个条件同时成立,如test -r file -a -x file,则file同时具有r与x权限时返回true
<2> -o 两个条件任何一个成立,如test -r file -o -x file,则file具有r或x权限时返回true
<3> ! 条件求反,如test ! -x file,则file不具备x权限时返回true
(7)判断符号[]
除了test外,还可以使用判断符号[]来进行数据的判断.其中,中括号[]的使用方法与test几乎完全一致,只是中括号多用在条件判断语句if...then...fi中.
Attention!!!
判断符号[]中每个组件中间都要用空格来分隔,比如:
#name="lishuai"
# [ "$name" == "lishuai" ]
1.第一个方括号的左右两边分别有一个空格,第二个方括号的左右两边也分别有一个空格,符号"=="与两边的组件之间也各有一个空格.
2.中括号[]内的变量最好用双引号来设置.
3.中括号[]内的常量最好用双引号或单引号来设置.
4.在Shell脚本语言中,"=="用于判断逻辑表达式,是"比较";"="用于给变量设置内容,是"设置".
(8)条件判断(if...then...语句)
Attention!!!
在Shell脚本中,&&和||的含义不同.
(1) &&表示AND
(2) ||表示or
条件判断if...then...语句是Shell脚本语言中逻辑控制语言,它有三种常用写法:
(1)第一种格式:类似于C语言的if语句,只需要一个fi表示if语句的结束.
if [ 条件判断表达式 ]; then
#当条件判断表达式成立时,可以执行的命令
fi
(2)第二种格式:类似于C语言的if...else语句,只需要一个fi表示if语句的结束
if [ 条件表达式 ]; then
#当条件判断表达式成立时,可以执行的命令
else
#当条件判断表达式不成立时,可以执行的命令
fi
(3)第三种格式:类似于C语言的if...else if...else...
if [ 条件表达式1 ]; then
#当条件表达式1成立时,可以执行的命令
elif [ 条件表达式2 ]; then
#当条件表达式2成立时,可以执行的命令
else
#当条件表达式1和2均不成立时,可以执行的命令
fi (9)条件判断(case...esac语句)
这种条件判断类似于C语言中的switch...case...语句,其格式为:
case $变量名 in
"第一个变量内容")
程序段
;;
"第二个变量内容")
程序段
;;
*)
不包含第一个变量内容与第二个变量内容的其它程序执行段
exit 1
;;
esac
Attenton!!!
(1)case语句最后必须以esac为结尾.
(2)每一个变量内容的程序段最后都需要两个分号来表示该程序段的结束.
(3)最后的"*"作用类似于C语言中的default.
(10)函数在Shell中的应用
函数在Shell脚本中可以简化很多程序代码.在Shell脚本中,函数必须先定义再调用,且必须在程序的最前面来定义,这样才能在执行时找到可用的程序段.它有固定的定义格式:
function 函数名() {
程序段
}
Attention!!!
函数两边的大括号不能在同一行.
(11)循环(while...do...done、until...do...done)
两种循环的区别:while是为真时执行,until是为假时执行.
(1)循环while...do...done的格式
当condition条件成立时,就进行循环,直到condition的条件不成立才停止.
while [ condition ]
do
程序段
done
(2)循环until...do...done的格式
当condition条件成立时就终止循环,否则就持续执行循环的程序段.
until [ condition ]
do
程序段
done (12)循环(for...do...done)
for循环结构与C语言中有所不同,在BASH中for循环有两种基本结构:
基本结构1:
for (( 初始值; 限制值; 执行步长 ))
do
程序段
done
Attention!!!
<1>这种写法主要用于数值运算.
<2>从上面的for格式可以看出,各个组件之间分别用空格分隔.其实也可以不用这些空格,但建议使用.
基本结构2:
for var in con1 con2 con3 ...
do
程序段
done
Attention!!!
<1>$var是循环控制变量,[list]是var需要遍历的一个集合,do/done对包含了循环体,相当于C语言中的一对大括号.另外,如果do和for被写在同一行,必须在do前面加上";",
如 for $var in [list];do
<2>for循环语句执行过程:
将[list]中的每一个值赋给变量$var,然后执行程序段的操作.
第1次循环时,$var的内容是con1
第2次循环时,$var的内容是con2
第3次循环时,$var的内容是con3
第4次循环时,... ...
<3>注意,在for所在的那一行,变量day是没有加"$"符号的,而在循环体内,echo所在行变量day必须加上"$"符号.这是因为在for所在的那一行是对变量day的赋值,而不是引用.在Linux中,只有对变量的引用时才加上"$"符号. (13)Shell脚本的追踪与调试
脚本在执行之前就怕出问题.Linux提供了不需要通过直接执行该脚本就判断是否有问题.
[root@localhost lishuai]# sh [-nvx] scripts.sh
参数:
-n 不执行脚本,仅检查语法问题
-v 在脚本执行前,先将脚本的内容输出到屏幕上
-x 将使用的脚本内容显示到屏幕上,这个参数最有用.
比如:有一脚本文件test.sh,在运行该脚本前害怕出问题,可以使用Linux提供的途径来检查该脚本是否有问题.
[root@localhost lishuai]# sh -x test.sh
-x参数可以在执行前列出所有要执行的程序段.如果是程序段,则输出时最前面会加上"+"符号,表示它是程序段.
Attention!!!
Linux中有大量的脚本文件,若不直到该脚本的功能,可以使用vim编辑器打开该脚本文件,通过系统对它的描述(description)就可以明白了.
相关阅读 更多 +