定义:
linux shell script是一组shell命令组成的批处理文件。类似于windows的bat文件。
shell脚本基本语法
- 每当读取到一个ENTER符号,就开始尝试执行该行的命令。
- 如果一行的命令太长,可以在行尾使用反斜杠将命令延续到下一行。
[root@localhost testsh]# cat testenter.sh echo zjf is a good man |
- #开头代表注释。
脚本的执行
脚本的执行方式在前几篇文章里有叙述。这里要重点关注这点:
sh和./的方式,需要的权限不一样。sh只需要接受一个参数,所以可读就可以,但是./需要执行权限。
[root@localhost testsh]# chmod 666 testenter.sh [root@localhost testsh]# sh testenter.sh zjf is a goodman [root@localhost testsh]# ./testenter.sh -bash: ./testenter.sh: 权限不够 |
数值运算
bash的数值运算可以执行简单的加减乘除,有两种方式:
- 直接进行数值运算
这种方式,需要让解释器知道当前处理的变量是数值型的。否则将不会进行数值运算。
如下:
错误的方式:
[root@localhost testsh]# x=10; [root@localhost testsh]# y=2 [root@localhost testsh]# z=x*y [root@localhost testsh]# echo $z x*y |
及时x和y是数值型的也不行:
[root@localhost testsh]# x=10 [root@localhost testsh]# declare -i y=2 [root@localhost testsh]# z=x*y [root@localhost testsh]# echo $z x*y |
必须声明z为数值型:
[root@localhost testsh]# x=10; [root@localhost testsh]# y=2 [root@localhost testsh]# declare -i z [root@localhost testsh]# z=x*y [root@localhost testsh]# echo $z 20 |
- 使用$((运算内容)),不需要声明数值类型。
注意,这里是两个括号。
[root@localhost testsh]# x=10 [root@localhost testsh]# y=2 [root@localhost testsh]# z=$((x*y)) [root@localhost testsh]# echo $z 20 |
条件逻辑
- 第一种方式,使用test命令。
test命令不返回true或者false结果,所以使用如下方式是达不到效果的。
if [ $(test -e /etc) ]; then echo 111 fi |
虽然不会报错,但是if条件是不会满足的。
可以通过$?获取test的返回状态码,来判断test成功或者失败。
[root@localhost testsh]# test -e /etc [root@localhost testsh]# echo $? 0 [root@localhost testsh]# test -e /etc1 [root@localhost testsh]# echo $? 1 |
正确的使用方式1:
[root@localhost testsh]# test -e /etc && echo "exists" || echo "not exists" exists |
其中,&&后面跟着执行test成功后执行的语句,||后面跟着test失败后执行的语句。
正确的使用方式2:
if test -e /etc then echo 111 fi |
test命令明细,没有必要全部记下来。但是要知道可以做什么:
判断字符串
test –n 字符串 字符串的长度非零
test –z 字符串 字符串的长度为零
test 字符串1=字符串2 字符串相等
test 字符串1!=字符串2 字符串不等
判断整数
test 整数1 –eq 整数2 整数相等
test 整数1 –ge 整数2 整数1大于等于整数2
test 整数1 –gt 整数2 整数1大于整数2
test 整数1 –le 整数2 整数1小于等于整数2
test 整数1 –lt 整数2 整数1小于整数2
test 整数1 –ne 整数2 整数1不等于整数2
判断文件
test File1 –ef File2 两个文件具有同样的设备号和i结点号
test File1 –nt File2 文件1比文件2 新
test File1 –ot File2 文件1比文件2 旧
test –b File 文件存在并且是块设备文件
test –c File 文件存在并且是字符设备文件
test –d File 文件存在并且是目录
test –e File 文件存在
test –f File 文件存在并且是正规文件
test –g File 文件存在并且是设置了组ID
test –G File 文件存在并且属于有效组ID
test –h File 文件存在并且是一个符号链接(同-L)
test –k File 文件存在并且设置了sticky位
test –b File 文件存在并且是块设备文件
test –L File 文件存在并且是一个符号链接(同-h)
test –o File 文件存在并且属于有效用户ID
test –p File 文件存在并且是一个命名管道
test –r File 文件存在并且可读
test –s File 文件存在并且是一个套接字
test –t FD 文件描述符是在一个终端打开的
test –u File 文件存在并且设置了它的set-user-id位
test –w File 文件存在并且可写
test –x File 文件存在并且可执行
多重条件判断:
- if test表达式 #表达式为真
- if test ! 表达式 #表达式为假 注意!前后有空格
- test 表达式1 –a 表达式2 #两个表达式都为真 a代表and
- test 表达式1 –o 表达式2 #两个表达式有一个为真 o代表or
[root@localhost testsh]# if test 1==1 ;then echo 111;fi; 111 [root@localhost testsh]# if test ! 1==1 ;then echo 111;fi;
[root@localhost testsh]# if test 1==1 -a -e /etc ;then echo 111;fi; 111 [root@localhost testsh]# if test 1==2 -o -e /etc ;then echo 111;fi; 111 |
- 第二种方式,使用[]
虽然 Linux 和 UNIX 的每个版本中都包含 test 命令,但该命令有一个更常用的别名 — 左方括号:[。test 及其别名通常都可以在 /usr/bin 或 /bin (取决于操作系统版本和供应商)中找到。当您使用左方括号而非 test 时,其后必须始终跟着一个空格、要评估的条件、一个空格和右方括号。右方括号不是任何东西的别名,而是表示所需评估参数的结束。条件两边的空格是必需的,这表示要调用 test,以区别于同样经常使用方括号的字符/模式匹配操作。
test 和 [ 的语法如下:
test expression
[ expression ]
[root@localhost testsh]# if [ "111"=="111" ]; then echo 111; fi; 111 [root@localhost testsh]# if [ -e /etc ]; then echo 111; fi; 111 |
字符串的比较
对字符串的比较,如果是变量一定要用""括起来
[root@localhost testsh]# if [ $name=="zjf man" ] ; then echo 111;fi; -bash: [: zjf: 期待一元表达式 [root@localhost testsh]# if [ "$name"=="zjf man" ] ; then echo 111;fi; 111 |
因为第一个命令其实变成了if [zjf man=="zjf man" ] ; then echo 111;fi;
判断为空的两种方式:
[root@localhost testsh]# unset name [root@localhost testsh]# if [ "$name"=="" ] ; then echo 111;fi; 111 [root@localhost testsh]# if [ -z "$name" ] ; then echo 111;fi; 111 |
if判断
if空格[空格条件判断空格 ] ; then
command
elif空格[空格条件判断空格 ] ; then
command
else
command
fi
其中,elif和else是可选的。
&&代表and。
||代表or。
[ "$i"=="1" -o "$j"=="1" ] 等于 [ "$i"=="1" ] || [ "$j"=="1" ]
[ "$i"=="1" -a "$j"=="1" ] 等于 [ "$i"=="1" ] && [ "$j"=="1" ]
function功能
[root@localhost testsh]# vim testfunction.sh
function print() { echo "$1" } print 11 print "zjf"
[root@localhost testsh]# sh testfunction.sh 11 zjf |
注意,定义的时候,括号内不能传递参数,参数是通过$1 $2来传递的。$0不是参数,是sh文件的名称。
调用方法的时候,不是通过括号传递参数的方式,而是和调用命令相同的方式。
loop循环
while空格[空格条件空格]
do
command
done
util空格[空格条件空格]
do
command
done
[root@localhost testsh]# vim testwhile.sh
declare -i i=0 declare -i sum=0 while [ $i -lt 100 ] do sum=sum+i i=i+1 done echo $sum
[root@localhost testsh]# sh testwhile.sh 4950 |
for in循环
[root@localhost testsh]# vim testfor.sh
users=$(cut -d ':' -f1 /etc/passwd) for username in $users do echo "i hava a user named $username" done
[root@localhost testsh]# sh testfor.sh i hava a user named root i hava a user named bin i hava a user named daemon i hava a user named adm |
for常见用法:
for i in $(seq 10) do 相当于for((i=1;i<=10;i++));
for i in f1 f2 f3 ;do
for i in $(ls)
for循环
注意有两个括号。
for((i=1;i<10000000;i++));do echo $i |