shell脚本学习
1、变量声明
# 在声明变量的时候,不用加$, 并且等号的两边不能留有空格
a=1111
# 引用变量的时候需要用$进行修饰
echo $a
# 如果只需要引用变量,那么可以使用$变量名即可,如果需要对变量做处理,那么就需要使用${}, 其他方法可以参看另外一篇内容
echo ${a:1:1} # 表示从变量a中截取顺序为1的且位数为1位
# 通过关键字export 把变量变为全局变量
export a # 注意这里不需要使用 $修饰
# 查询全局是否有该变量
env | grep ^a # 注意这里使用的是 ^符号
# 删除变量使用关键字,并且前面也不使用$修饰
unset a
变量声明的方法
# 声明数字, 使用关键字 declare
declare -i a=1
declare -i b=2
declare -i c=$a+$b
# 声明只读的变量
declare -r a="test" # 这个时候即不可以用unset删除,也不能重新赋值,但是退出终端即消失
# 声明全局变量
declare -x even="even" # 相当于export出去
# 声明索引数组 -a
# 声明关联数组 -A
普通数组的定义方式
# 方式一
arr[0]=1
arr[1]=2
# 方式二, 注意该方式中是用空隔隔开的
arr=(1 2 3)
# 查询数组所有项
echo ${arr[*]}
# 查询数组的长度
echo ${#arr[*]}
# 查询数组里的索引下标
echo ${!arr[*]}
# 获取数组指定的项
echo ${arr[*]:1:1}
# 可以把命令结果赋值给数组
arr=($(ls ./))
# 查看所有的数组
declare -a
关联数组的定义
# 方式一
declare -A arr
arr[first]=aaa
arr[second]=bbb
# 方式二
declare -a array
array=([aaa]=AAA [bbb]=BBB)
# 其他的操作与普通数组一致
交互式变量定义
交互式变量定义的值 read 主要用于让用户去定义变量值
-p 提示信息
-n 字符数(限制变量的字符数)
-s 不显示
-t 超时(默认单位秒)(限制用户输入变量值的时间)
# 提示用户输入用户名
read -p "please input your name" name
echo $name # 可以输出用户输入的用户名
# 提示用户输入密码
read -s -p "please input your password" pass
echo $pass # 可以输出用户输入的密码
# 从文件中读取指定的字段
read name pass < test.txt # test.txt的内容是 aaa pass 注意分隔符是空隔
echo $name $pass #则可以输出指定的字段
# 一次指定多个字段
read name age #这时用户按次输入的值会被赋值给name与age, 达到一次赋值两个变量, 注意用空格隔开
2、变量的处理
1、${VAR:-DEFAULT},VAR没有定义或者为空则输出$DEFAULT的值(VAR不变)
echo ${test:-test} # 没有定义test的前提下,会使用 -后面的值,但是test的值还是空
2、${VAR:=DEFAULT},VAR没有定义或空则为$DEFAULT的值
echo ${test:=test} # 与上面不一样的是,test会被赋值为test
3、${#test} # 返回test这个变量值的长度
4、${test^^},把test中的所有小写字母转换为大写输出(不改变值)
5、${STR:POSITON},从$POSITON位置提取子串
6、${STR:POSITON:LENGTH},从$POSITON位置提取长度为$LENGTH子串
7、
${STR%SUBSTR},从$STR尾部查找匹配,删除最短匹配$SUBSTR的子串(正常顺序)
${STR%%SUBSTR},从$STR尾部查找匹配,删除最长匹配$SUBSTR的子串(正常顺序)
temp=/etc/nginx/conf.d/default.conf
echo ${temp%.*} # 输出 /etc/nginx/conf.d/default
echo ${temp%%.*} # 输出 /etc/nginx/conf
8、
${STR#SUBSTR},从$STR头查找匹配,删除最短匹配$SUBSTR的子串(非正常顺序)
${STR##SUBSTR},从$STR头部查找匹配,删除最长匹配$SUBSTR的子串(非正常顺序)
temp=/etc/nginx/conf.d/default.conf
echo ${temp#*.} # 输出 d/default.conf
echo ${temp##*.} # 输出 conf (可以利用该方法来获取extname)
3、简单的四则运算
默认情况下,shell就只能支持简单的==整数==运算
shell支持下面几种运算符
+ - * / %(取模,求余数)
Bash shell 的算术运算有四种方式:
1. 使用 $(( ))
2. 使用 $[ ]
3. 使用 expr 外部程式
4. 使用 let 命令(一般使用该语句进行再赋值操作)
(注意使用以下的运算符的时候,不需要使用$对值进行引用 如: a=1;b=2 echo $(( a+b )) )
注意: n=1 let n+=1 等价于let n=n+1
# 如果需要进行小数运算, 需要借助bc工具, 如果未安装,使用yum y install bc
[root@server shell01]# echo 1+1.5|bc
注意: i++ 与 ++i的区别在于前者是先赋值后计算,后者是先计算再赋值
a=1;b=1; let $c=a++ 与 let $d=++b 那么$c与$d的值是不一样的
4、条件判断
-
-
格式2: [ 条件表达式 ]
-
格式3: [[ 条件表达式 ]] 支持正则
-e 是否存在 不管是文件还是目录,只要存在,条件就成立
-f 是否为普通文件
-d 是否为目录
-S socket
-p pipe
-c character
-b block
-L 软link
三种语法格式:
test -e file 只要文件存在条件为真
[ -d /shell01/dir1 ] 判断目录是否存在,存在条件为真
[ ! -d /shell01/dir1 ] 判断目录是否存在,不存在条件为真
[[ -f /shell01/1.sh ]] 判断文件是否存在,并且是一个普通的文件
-s 判断文件是否有内容(大小),非空文件条件满足
说明:-s表示非空,! -s 表示空文件
说明:1.sh文件里有内容的。
[root@server shell01]# test -s 1.sh
[root@server shell01]# echo $?
0
[root@server shell01]# touch aaa
[root@server shell01]# cat aaa
[root@server shell01]# test -s aaa
[root@server shell01]# echo $?
1
[root@server shell01]# test ! -s aaa;echo $?
0
[root@server shell01]# test ! -s 1.sh
[root@server shell01]# echo $?
1
文件权限相关的判断
-r 当前用户对其是否可读
-w 当前用户对其是否可写
-x 当前用户对其是否可执行
-u 是否有suid
-g 是否sgid
-k 是否有t位
两个文件的比较判断
file1 -nt file2 比较file1是否比file2新
file1 -ot file2 比较file1是否比file2旧
file1 -ef file2 比较是否为同一个文件,或者用于判断硬连接,是否指向同一个inode
test file1 -nt file2
[ file1 -ot file2 ]
整数之间的判断
-eq 相等
-ne 不等
-gt 大于
-lt 小于
-ge 大于等于
-le 小于等于
字符串之间的判断
-z 是否为空字符串 字符串长度为0,就成立
-n 是否为非空字符串 只要字符串非空,就是成立
string1 = string2 是否相等
string1 != string2 不等
[root@server shell01]# AAA=hello
[root@server shell01]# BBB=world
[root@server shell01]# test -z $AAA
[root@server shell01]# echo $?
1
[root@server shell01]# test -n $AAA
[root@server shell01]# echo $?
0
[root@server shell01]# [ $AAA = $BBB ]
[root@server shell01]# echo $?
1
[root@server shell01]# [ $AAA != $BBB ]
[root@server shell01]# echo $?
0
多重条件判断
逻辑判断符号:
-a 和 && (and 逻辑与) 两个条件同时满足,整个大条件为真
-o 和 || (or 逻辑或) 两个条件满足任意一个,整个大条件为真
[ 1 -eq 1 -a 1 -ne 0 ] 整个表达式为真
[ 1 -eq 1 ] && [ 1 -ne 0 ]
[ 1 -eq 1 -o 1 -ne 1 ] 整个表达式为真
[ 1 -eq 1 ] || [ 1 -ne 1 ]
[root@server shell01]# [ 1 -eq 0 ] && echo true || echo false
false
[root@server shell01]# [ 1 -eq 1 ] && echo true || echo false
true
&&:前面的表达式为真
||:前面的表达式为假
总结:
1、; && ||都可以用来分割命令或者表达式
2、; 完全不考虑前面的语句是否正确执行,都会执行;号后面的内容
3、&& 需要考虑&&前面的语句的正确性,前面语句正确执行才会执行&&后的内容;反之亦然
make && make install
4、|| 需要考虑||前面的语句的非正确性,前面语句执行错误才会执行||后的内容;反之亦然
5、如果&&和||一起出现,从左往右依次看,按照以上原则
数值比较示例
示例:
数值比较:
[root@server ~]# [ $(id -u) -eq 0 ] && echo "the user is admin" # $(id -u) 表示获取用户id
[root@server ~]$ [ $(id -u) -ne 0 ] && echo "the user is not admin"
[root@server ~]$ [ $(id -u) -eq 0 ] && echo "the user is admin" || echo "the user is not admin"
[root@server ~]# uid=`id -u`
[root@server ~]# test $uid -eq 0 && echo this is admin
this is admin
[root@server ~]# [ $(id -u) -ne 0 ] || echo this is admin
this is admin
[root@server ~]# [ $(id -u) -eq 0 ] && echo this is admin || echo this is not admin
this is admin
[root@server ~]# su - stu1
[stu1@server ~]$ [ $(id -u) -eq 0 ] && echo this is admin || echo this is not admin
this is not admin
[stu1@server ~]$
类C风格的数值比较:
注意:在(( ))中,=表示赋值;==表示判断
1159 ((1==2));echo $?
1160 ((1<2));echo $?
1161 ((2>=1));echo $?
1162 ((2!=1));echo $?
1163 ((`id -u`==0));echo $?
1209 ((a=123));echo $a
1210 unset a
1211 ((a==123));echo $?
字符串比较:
注意:双引号引起来,看作一个整体;= 和 == 在 [ 字符串 ] 比较中都表示判断
1196 a='hello world';b=world
1197 [ $a = $b ];echo $?
1198 [ "$a" = "$b" ];echo $?
1199 [ "$a" != "$b" ];echo $?
1200 [ "$a" !== "$b" ];echo $? 错误
1201 [ "$a" == "$b" ];echo $?
1202 test "$a" != "$b";echo $?
思考:[ ] 和 [[ ]] 有什么区别?
1213 a=
1214 test -z $a;echo $?
1215 a=hello
1216 test -z $a;echo $?
1217 test -n $a;echo $?
1217 test -n "$a";echo $?
# [ '' = $a ];echo $?
-bash: [: : unary operator expected
2
# [[ '' = $a ]];echo $?
0
1278 [ 1 -eq 0 -a 1 -ne 0 ];echo $?
1279 [ 1 -eq 0 && 1 -ne 0 ];echo $?
1280 [[ 1 -eq 0 && 1 -ne 0 ]];echo $?