###1. 变量的分类
本地变量:当前用户自定义的变量。当前进程中有效,其他进程及当前进程的子进程无效。
环境变量:当前进程有效,并且能够被子进程调用。
查看当前用户的环境变量 env
查询当前用户的所有变量(临时变量与环境变量) set
export //将当前变量变成环境变量
[root@MissHou tmp]# export A=hello //临时将一个本地变量(临时变量)变成环境变量 [root@MissHou tmp]# env|grep ^A A=hello 永久生效: vim /etc/profile 或者 ~/.bashrc export A=hello 或者 A=hello export A 说明:系统中有一个变量PATH,环境变量 export PATH=/usr/local/mysql/bin:$PATH
全局变量:全局所有的用户和程序都能调用,且继承,新建的用户也默认能调用.
$HOME/.bashrc 当前用户的bash信息(aliase、umask等) $HOME/.bash_profile 当前用户的环境变量() oracle——>oracle用户——>$oracle/.bash_profile——>export home_install=/u01/app/xxx $HOME/.bash_logout 每个用户退出当前shell时最后读取的文件 /etc/bashrc 使用bash shell用户全局变量 grep --color=auto umask /etc/profile 系统和每个用户的环境变量信息 mycat_home=/usr/local/mycat/bin export mycat_home 执行mycat命令 # mycat $ mycat 用户登录系统读取相关文件的顺序: /etc/profile——>$HOME/.bash_profile——>$HOME/.bashrc——>/etc/bashrc——>$HOME/.bash_logout source /etc/bashrc
系统变量(内置bash中变量) : shell本身已经固定好了它的名字和作用.
$?:上一条命令执行后返回的状态,当返回状态值为0时表示执行正常,非0值表示执行异常或出错
若退出状态值为0,表示命令运行成功
若退出状态值为127,表示command not found
若退出状态值为126,表示找到了该命令但无法执行(权限不够)
若退出状态值为1&2,表示没有那个文件或目录
$$:当前所在进程的进程号 echo $$ eg:kill -9 `echo $$` = exit 退出当前会话
$!:后台运行的最后一个进程号 (当前终端) # gedit &
!$ 调用最后一条命令历史中的参数
!! 调用最后一条命令历史
$#:脚本后面接的参数的个数
$*:脚本后面所有参数,参数当成一个整体输出,每一个变量参数之间以空格隔开
$@: 脚本后面所有参数,参数是独立的,也是全部输出
$0:当前执行的进程/程序名 echo $0
$1~$9 位置参数变量
${10}~${n} 扩展位置参数变量 第10个位置变量必须用{}大括号括起来
./1.sh a b c
[root@MissHou shell01]# cat 2.sh
#!/bin/bash
#xxxx
echo "\$0 = $0"
echo "\$# = $#"
echo "\$* = $*"
echo "\$@ = $@"
echo "\$1 = $1"
echo "\$2 = $2"
echo "\$3 = $3"
echo "\$11 = ${11}"
echo "\$12 = ${12}"
了解$*和$@的区别:
$* :表示将变量看成一个整体
$@ :表示变量是独立的
#!/bin/bash
for i in "$@"
do
echo $i
done
echo "======我是分割线======="
for i in "$*"
do
echo $i
done
[root@MissHou shell01]# bash 3.sh a b c
a
b
c
======我是分割线=======
a b c
###2. 什么时候需要定义变量?
如果某个内容需要多次使用,并且在代码中重复出现,那么可以用变量代表该内容。这样在修改内容的时候,仅仅需要修改变量的值。
在代码运作的过程中,可能会把某些命令的执行结果保存起来,后续代码需要使用这些结果,就可以直接使用这个变量。
###3. 变量的定义规则
1. 默认情况下,shell里定义的变量是不分类型的,可以给变量赋与任何类型的值;等号两边不能有空格,对于有空格的字符串做为赋值时,要用引号引起来
变量名=变量值
2. 变量的获取方式: $变量名 ${变量名}
[root@MissHou shell01]# a=12345678
[root@MissHou shell01]# echo $a
12345678
[root@MissHou shell01]# echo ${a}
12345678
[root@MissHou shell01]# echo ${a:2:3} a表示变量名;2表示从第3个字符开始;3表示后面3个字符
345
如果获取变量的全部两个都可以;如果获取变量的某一部分,用${}
3. 取消变量: unset 变量名
4. 变量名区分大小写,同名称但大小写不同的变量名是不同的变量
5. 变量名可以是字母或数字或下划线,但是不能以数字开头或者特殊字符
[root@MissHou shell01]# 1a=hello
-bash: 1a=hello: command not found
[root@MissHou shell01]# ?a=hello
-bash: ?a=hello: command not found
[root@MissHou shell01]# _a=hello
[root@MissHou shell01]# echo $_a
hello
6. 命令的执行结果可以保存到变量
[root@server shell01]# kernel=`uname -r`
[root@server shell01]# echo $kernel
2.6.32-431.el6.x86_64
[root@server shell01]# name=$(uname -n)
[root@server shell01]# echo $name
server.itcast.cc
7. 有类型变量 declare
-i 将变量看成整数
-r 使变量只读 readonly
-x 标记变量通过环境导出 export
-a 指定为索引数组(普通数组);查看普通数组
-A 指定为关联数组;查看关联数组
[root@server shell01]# a=10
[root@server shell01]# b=20
[root@server shell01]# echo $a+$b
10+20
[root@server shell01]# declare -i a=2
[root@server shell01]# declare -i b=4
[root@server shell01]# declare -i c=$a+$b
[root@server shell01]# echo $c
6
[root@server shell01]# AAAA=hello
[root@server shell01]# export AAAA
[root@server shell01]# env|grep AAAA
AAAA=hello
[root@server shell01]# declare -x BBBB=hello
[root@server shell01]# env|grep BBBB
BBBB=hello
8. 数组
普通数组:只能使用整数作为数组索引(元素的下标)
关联数组:可以使用字符串作为数组索引(元素的下标)
普通数组定义:用括号来表示数组,数组元素(变量)用“空格”符号分割开。定义数组的一般形式为:
一次赋一个值:
变量名=变量值
array[0]=v1
array[1]=v2
array[3]=v3
一次赋多个值:
array=(var1 var2 var3 var4)
array1=(`cat /etc/passwd`) //将文件中每一行赋值给array1数组
array2=(`ls /root`)
array3=(harry amy jack "Miss Hou")
array4=(1 2 3 4 "hello world" [10]=linux)
读取数组:
${array[i]} i表示元素的下标
使用@ 或 * 可以获取数组中的所有元素:
获取第一个元素
echo ${array[0]}
echo ${array[*]} 获取数组里的所有元素
echo ${#array[*]} 获取数组里所有元素个数
echo ${!array[@]} 获取数组元素的索引下标
echo ${array[@]:1:2} 访问指定的元素;1代表从下标为1的元素开始获取;2代表获取后面几个元素
[root@server shell01]# array[0]=var1
[root@server shell01]# array[1]=var2
[root@server shell01]# array[2]=var3
[root@server shell01]# array1=(uu1 uu2 uu3 uu4)
[root@server shell01]# ls
1.sh 2.sh 3.sh 4.sh passwd
[root@server shell01]# array2=(`ls ./`)
[root@server shell01]# array3=(jack harry "Miss Hou" [5]=tom)
查看普通数组信息:
[root@server shell01]# declare -a
declare -a array='([0]="var1" [1]="var2" [2]="var3")'
declare -a array1='([0]="uu1" [1]="uu2" [2]="uu3" [3]="uu4")'
declare -a array2='([0]="1.sh" [1]="2.sh" [2]="3.sh" [3]="4.sh" [4]="passwd")'
declare -a array3='([0]="jack" [1]="harry" [2]="Miss Hou" [5]="tom")'
[root@server shell01]#
[root@server shell01]#
[root@server shell01]# echo ${array[*]}
var1 var2 var3
[root@server shell01]# echo ${array[@]}
var1 var2 var3
[root@server shell01]# echo ${array[2]}
var3
[root@server shell01]# echo ${array2[@]}
1.sh 2.sh 3.sh 4.sh passwd
[root@server shell01]# echo ${array2[3]}
4.sh
[root@server shell01]#
[root@server shell01]# echo ${array2[*]:2:2}
3.sh 4.sh
[root@server shell01]# echo ${#array2[*]}
5
[root@server shell01]# echo ${!array2[*]}
0 1 2 3 4
[root@server shell01]# echo ${!array3[*]}
0 1 2 5
关联数组定义:
首先声明关联数组
declare -A asso_array1
declare -A asso_array2
declare -A asso_array3
数组赋值:
一次赋一个值:
数组名[索引|下标]=变量值
[root@server ~]# asso_array1[linux]=one
[root@server ~]# asso_array1[java]=two
[root@server ~]# asso_array1[php]=three
一次赋多个值:
[root@server ~]# asso_array2=([name1]=harry [name2]=jack [name3]=amy [name4]="Miss Hou")
查看关联数组:
[root@server ~]# declare -A
declare -A asso_array1='([php]="three" [java]="two" [linux]="one" )'
declare -A asso_array2='([name3]="amy" [name2]="jack" [name1]="harry" [name4]="Miss Hou" )'
[root@server ~]# echo ${asso_array1[linux]}
one
[root@server ~]# echo ${asso_array1[php]}
three
[root@server ~]# echo ${asso_array1[*]}
three two one
[root@server ~]# echo ${!asso_array1[*]}
php java linux
[root@server ~]# echo ${#asso_array1[*]}
3
[root@server ~]# echo ${#asso_array2[*]}
4
[root@server ~]# echo ${!asso_array2[*]}
name3 name2 name1 name4
9. 交互式定义变量的值 read 主要用于让用户去定义变量值
-p 提示信息
-n 字符数 (限制变量值的字符数)
-s 不显示
-t 超时(默认单位秒)(限制用户输入变量值的超时时间)
[root@MissHou shell01]# cat 1.txt
10.1.1.1 255.255.255.0
[root@MissHou shell01]# read -p "Input your IP and Netmask:" ip mask < 1.txt
[root@MissHou shell01]# echo $ip
10.1.1.1
[root@MissHou shell01]# echo $mask
255.255.255.0
10. 其他变量(扩展)
1)取出一个目录下的目录和文件:dirname和 basename
2)变量"内容"的删除和替换
一个“%”代表从右往左去掉一个/key/
两个“%%”代表从右往左最大去掉/key/
一个“#”代表从左往右去掉一个/key/
两个“##”代表从左往右最大去掉/key/
# A=/root/Desktop/shell/mem.txt
# echo $A
/root/Desktop/shell/mem.txt
# dirname $A 取出目录
/root/Desktop/shell
# basename $A 取出文件
mem.txt
# url=www.taobao.com
# echo ${#url} 获取变量的长度
# echo ${url#*.}
# echo ${url##*.}
# echo ${url%.*}
# echo ${url%%.*}
++++++++++++++++++++++++++++++++++++++++++++++++++
以下内容自己完成:
替换:/ 和 //
1015 echo ${url/ao/AO}
1017 echo ${url//ao/AO} 贪婪替换
替代: - 和 :- +和:+
1019 echo ${abc-123}
1020 abc=hello
1021 echo ${abc-444}
1022 echo $abc
1024 abc=
1025 echo ${abc-222}
${变量名-新的变量值} 或者 ${变量名=新的变量值}
变量没有被赋值:会使用“新的变量值“ 替代
变量有被赋值(包括空值): 不会被替代
1062 echo ${ABC:-123}
1063 ABC=HELLO
1064 echo ${ABC:-123}
1065 ABC=
1066 echo ${ABC:-123}
${变量名:-新的变量值} 或者 ${变量名:=新的变量值}
变量没有被赋值或者赋空值:会使用“新的变量值“ 替代
变量有被赋值: 不会被替代
1116 echo ${abc=123}
1118 echo ${abc:=123}
[root@server ~]# unset abc
[root@server ~]# echo ${abc:+123}
[root@server ~]# abc=hello
[root@server ~]# echo ${abc:+123}
123
[root@server ~]# abc=
[root@server ~]# echo ${abc:+123}
${变量名+新的变量值}
变量没有被赋值或者赋空值:不会使用“新的变量值“ 替代
变量有被赋值: 会被替代
[root@server ~]# unset abc
[root@server ~]# echo ${abc+123}
[root@server ~]# abc=hello
[root@server ~]# echo ${abc+123}
123
[root@server ~]# abc=
[root@server ~]# echo ${abc+123}
123
${变量名:+新的变量值}
变量没有被赋值:不会使用“新的变量值“ 替代
变量有被赋值(包括空值): 会被替代
[root@server ~]# unset abc
[root@server ~]# echo ${abc?123}
-bash: abc: 123
[root@server ~]# abc=hello
[root@server ~]# echo ${abc?123}
hello
[root@server ~]# abc=
[root@server ~]# echo ${abc?123}
${变量名?新的变量值}
变量没有被赋值:提示错误信息
变量被赋值(包括空值):不会使用“新的变量值“ 替代
[root@server ~]# unset abc
[root@server ~]# echo ${abc:?123}
-bash: abc: 123
[root@server ~]# abc=hello
[root@server ~]# echo ${abc:?123}
hello
[root@server ~]# abc=
[root@server ~]# echo ${abc:?123}
-bash: abc: 123
${变量名:?新的变量值}
变量没有被赋值或者赋空值时:提示错误信息
变量被赋值:不会使用“新的变量值“ 替代
说明:?主要是当变量没有赋值提示错误信息的,没有赋值功能
##简单的四则运算
算术运算:默认情况下,shell就只能支持简单的==整数==运算
+ - * / %(取模,求余数)Bash shell 的算术运算有四种方式: 1. 使用 $(( )) 2. 使用$[ ] 3. 使用 expr 外部程式 4. 使用let 命令 注意: n=1 let n+=1 等价于let n=n+1 思考:能不能用shell做小数运算? [root@server shell01]# echo 1+1.5|bc 2.5 i++ 和 ++i (了解) 对变量的值的影响: [root@node1 ~]# i=1 [root@node1 ~]# let i++ [root@node1 ~]# echo $i 2 [root@node1 ~]# j=1 [root@node1 ~]# let ++j [root@node1 ~]# echo $j 2 对表达式的值的影响: [root@node1 ~]# unset i j [root@node1 ~]# i=1;j=1 [root@node1 ~]# let x=i++ 先赋值,再运算 [root@node1 ~]# let y=++j 先运算,再赋值 [root@node1 ~]# echo $i 2 [root@node1 ~]# echo $j 2 [root@node1 ~]# echo $x 1 [root@node1 ~]# echo $y 2
总结:
$(()) $[] expr 注意空格,*要进行转义 \ let n+=1 等价 let n=n+1 let n=n**5 n有初值,然后求次幂 i++ ++i 对变量本身没有影响(自己+1); 表达式中有影响;i++ 先赋值再运算 ++i先运算再赋值 let x=i++ let x=++i
##条件判断
###1. 语法格式
格式1: ==test== 条件表达式
格式2: [ 条件表达式 ]
格式3: [[ 条件表达式 ]] 支持正则 =~
说明:
man test去查看,很多的参数都用来进行条件判断
###2. 条件判断相关参数
与文件存在与否的判断
-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 [root@server shell01]# 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、如果&&和||一起出现,从左往右依次看,按照以上原则
###3. 示例
示例: 数值比较: [root@server ~]# [ $(id -u) -eq 0 ] && echo "the user is admin" [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 $?
难学