shell script 是利用shell的功能所写的一个程序,这个程序是使用纯文本文件,将一些shell的语法与命令(含外部命令)写在里面,搭配正则表达式、管道命令与数据流重定向等功能,以达到我们所想要的处理目的。
shell script 的编写中还需要用到下面的注意事项:
1、命令的执行是从上而下、从左到右的分析与执行
2、命令的执行中命令、参数减的多个空白都会被忽略掉
3、空白行也将被忽略掉,并且【tab】按键所得的空白同样视为空格键
4、如果读取到一个Enter符号(CR),就尝试开始执行该行(或该串)命令
5、至于如果一行的内容太多,则可以使用"\[Enter]"来扩展至下一行
6、"#"可作为批注。任何加在#后面的数据将全部被视为批注文字而被忽略。
执行shell script的方法
1、直接命令执行:shell.sh文件必须要具备可读与可执行(rx)的权限 ,然后:
(1)绝对路径:使用/home/dmtsai/shell.sh来执行命令
(2)相对路径:假设工作目录在/home/dmtsai/,则使用./shell.sh来执行
(3)变量"PATH"功能:将shell.sh放在PATH指定的目录内,例如:~/bin/ 。
2、以bash进程来执行:通过"bash shell.sh"或"sh shell.sh"来执行。此时你的shell.sh只要有r的权限即可被执行。
eg1: #!/bin/bash => 声明这个script使用的shell名称
echo -e "Hello World! \a \n" => 程序内容
exit 0 => exit n(n是数字),利用exit让程序中断,并且回传一个数值给系统,exit 0 代表离开script并且 回传一个0给系统
数值运算: 在数值运算上,我们可以使用"declare -i total=$firstnu * secnu",也可以使用var =$((运算内容)),运算符有+、-、*、/、%等。
script的执行方式区别:
* 利用直接执行的方式执行script
直接命令执行(不论是绝对路径/相对路径还是$PATH内),或者是利用bash(或sh)来执行脚本时,该script都会使用一个新的bash环境来执行脚本内的命令。也就是说,使用这种执行方式时,其实script是在子进程的bash内执行的。当子进程完成后,子进程内的各项变量或操作将会结束而不会传回到父进程中。
*利用source来执行脚本:在父进程中执行
使用source对script执行,会在父进程中执行,因此各项操作都会在原本的bash内生效;这也是为啥不注销系统而要让某些写入~/.bashrc的设置生效时,需要使用"source ~/.bashrc" 而不使用"bash ~/.bashrc"。
利用test命令的测试功能
关于某个文件名的"文件类型"判断,如 test -e filename表示存在否
-e | 该文件名是否存在 |
-f | 该文件名是否存在且为文件(file) |
-d | 该文件名是否存在且为目录 |
关于文件的权限检测,如test -r filename 表示可读否(但root权限常有例外)
-r | 检测该文件名是否存在且具有"可读"权限 |
-w | 检测该文件名是否存在且具有"可写"权限 |
-x | 检测该文件名是否存在且具有"可执行"权限 |
关于两个文件之间的比较,如 test file1 -nt file2
-nt | newer than,判断file1是否比file2新 |
-ot | older than,判断file1是否比file2旧 |
-ef | 判断是否为同一文件 |
关于两个整数之间的判定 ,如 test n1 -eq n2
-eq | 两个值相等 |
-ne | 两个值不等 |
-gt | n1大于n2 |
-lt | n1小于n2 |
-ge | n1 大于等于n2 |
-le | n1小于等于 n2 |
多重条件判定,如 test -r filename -a -x filename
-a | 两条件同时成立 |
-o | 任何一条件成立 |
! | 反向状态 |
利用判断符号[]
利用判断符号"[]"来进行数据的判断,中括号用在很多地方,包括通配符与正则表达式等,所以如果要在bash的语法当中使用中阔或作为shell判断式时,必须要注意中括号的两端需要有空格符来分隔。 eg [ "$HOME" == "$MAIL" ]
用法注意:
中括号的使用方法与test几乎一摸一样,其中-o表示或(or),-a表示和(and)
test $HOME = $MAIL 相当于 [ "$HOME" == "$MAIL" ]
eg1: #!/bin/bash
read -p "please input(Y/N): " yn
[ "$yn" == "Y" -o "$yn" == "y" ] && echo "OK,continue" && exit 0
[ "$yn" == "N" -o "$yn" == "n" ] && echo "Oh,interrupt" && exit 0
echo "I don't know what your choice is" && exit 0
shell script 的默认变量($0,$1,$2....)
shell script 能够在脚本文件名后面带有参数
/path/to/scriptname opt1 opt2 opt3 opt4
$0 $1 $2 $3 $4
在shell script文件内可以直接使用$0,$1,$2...
$#: 代表后接的参数“个数”
$@: 代表“$1”,"$2","$3","$4"之意,每个变量是独立的(用双引号括起来)
$*: 代表“$1c$2c$3c$4”,其中c为分隔字符,默认为空格键,所以本例中代表"$1$2$3$4"之意
shift:造成参数变量号码偏移
在shell script 脚本中使用shift,会移动变量,而且shift后面可以接数字,代表拿掉最前面的几个参数的意思。此参数为执行脚本文件后面带的参数。
条件判断式
1、利用if...then
(1)单层、简单条件判断式
if [条件判断式]; then
当条件判断式成立时,可以进行的命令工作内容
fi
条件判断式 例如[ "$yn" == 'Y' -o "$yn" == 'y' ]这种将多个条件写入一个中括号内的情况外,还可以有多个中括号隔开,使用&& 或 || 来隔开,&&代表AND,||代表or, 上式可替换成[ "$yn" == 'Y' ]||[ "$yn" == 'y' ]
(2)多重、复杂条件判断式
if [条件判断式];then
当条件判断式一成立时,可以进行的命令工作内容;
elif [条件判断式二];then
当条件判断式二成立时,可以进行的命令工作内容
else
当条件判断式一与二均不成立时,可以进行的命令工作内容
fi
2、利用case.....esac判断
case $变量名称 in
"第一个变量内容")
程序段
;;
"第二个变量内容")
程序段
;;
*)
不包含第一个变量内容与第二个变量内容的其他程序执行段
;;
esac
一般来说,使用"case $变量 in"这个语法中,当中的那个“$变量”大致有两种取得方式:
直接执行方式:利用“script.sh variable”的方式来直接给予$1这个变量的内容,这也是在/etc/init.d目录下大多数程序的设计方式。比如 /etc/init.d/syslog restart
交互式:通过read这个命令来让用户输入变量的内容
eg: vi sh09.sh
#!/bin/bash
case $1 in
"hello")
echo "hello,how are you ?"
;;
" ")
echo "You must input parameters, ex>{$0 someword}"
;;
*)
echo "Usage $0 {hello}"
;;
esac
function功能
function是函数功能,函数可以在shell script当中做出一个类似自定义执行命令的东西。shell script的执行方式是由上而下,由左到右,因此在shell script当中function一定在程序最前面。
function fname(){
程序段
}
另外,function也是拥有内置变量的。它的内置变量与shell script很类似,函数名称代表$0,而后续接的变量也是以$1,$2...来替代的。这里很容易搞错,因为“function fname(){程序段}”内的$0,$1等与shell script的$0,$1是不同的。
#!/bin/bash
function printit(){
echo "Your choice is $1"
}
printit 1
循环
while do done, until do done (不定循环)
不定循环城建的两种状态:
(1) while [condition]
do
程序段落
done
这种方式说的是condition条件成立时,就进行循环,直到condition条件不成立才停止。
(2)until [condition]
do
程序段落
done
这种方式恰恰与while相反,它是当condition条件成立时,就终止循环,否则就持续进行循环的程序段。
eg1: #!/bin/bash
while [ "$yn" != "yes" -a "$yn" != "YES" ]
do
read -p "please input yes/YES to stop this program:" yn
done
echo "OK! you input the correct answer."
或 until [ "$yn" == "yes" -o "$yn" == 'YES' ]
do
read -p "please input yes/YES to stop this program: " yn
done
for ...do ...done(固定循环)
(1)for var in con1 con2 con3...
do
程序段
done
以上面的例子来说,这个$var 的变量内容在循环工作时
1、第一次循环时,$var的内容为con1
2、第二次循环时,$var的内容为con2
3、第三次循环时,$var的内容为con3
eg1: #!/bin/bash
users=$(cut -d ":" -f 1 /etc/passwd)
for username in $users
do
id $username
finger $username
done
(2) for ((初始值;限制值;执行步长))
do
程序段
done
这种语法适合于数值方式的运算当中,在for后面的括号内的三串内容意义:
初始值:某个变量在循环当中的初始值,直接以类似i=1设置好;
限制值:当变量值在这个限制值的范围内,就继续进行循环,例i<=100
执行步长:每做一次循环时变量的变化量。例i=i+1或i++
eg1: #!/bin/bash
read -p "please input a number" nu
s=0
for((i=1;i<=$nu;i=i+1))
do
s=$(($s+$i))
done
echo "The result of '1+2+3+...+$nu' is ==> $s"
shell script 的追踪与调试
sh [-nvx] script.sh
-n | 不要执行script,仅查询语法问题 |
-v | 在执行script前,先将script的内容输出到屏幕上 |
-x | 将使用到的script内容显示到屏幕上,这时很有用的参数 |