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、条件判断

  • 格式1: test  条件表达式

  • 格式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 $?