day 52 shell变量知识进阶与实践
1、shell特殊重要变量
$0 获取当前执行shell脚本的文件名,如果执行脚本带路径,那么包括脚本路径
(就是脚本的名字)
$n 获取当前执行shell脚本的第n个参数值,n=1..9,当n为0时表示脚本的文件名,如果n大于9,则用大括号括起来,例如${10},接的参数以空格隔开
(就是脚本里大于$9的数字用{}括起来,才能识别,命令行可以{a..z}这样用)
$# 获取当前执行shell脚本后面接的参数的总个数
(就是显示你脚本后面有几个参数)
$* 获取当前shell脚本所有传参的参数,不加引号作用同$@;如果给$*加上双引号,例如:"$*",则表示将所有的参数视为单个字符串,相当于"$1 $2 $3"
$@ 获取当前shell脚本所有传参的参数,不加引号作用同$*,如果给$@加上双引号,例如: "$@",则表示将所有的参数视为不同的独立字符串,相当于"$1" "$2" "$3" "..." ,这是将多参数传递给其他程序的最佳方式,因为它会保留所有内嵌在每个参数里的任何空白。当"$@"和"$*"都加双引号时,二者有区别,都不加双引号时,二者无区别
案列:
[root@web01 /server/scripts]# vim 1.sh
if [ $# -eq 0 ]
then
echo "Usage: $0 {start|stop|restart}"
fi
echo $1
[root@web01 /server/scripts]# sh 1.sh
Usage: 1.sh {start|stop|restart}
[root@web01 /server/scripts]# set -- "I am" handsome oldboy
[root@web01 /server/scripts]# echo $1
I am
[root@web01 /server/scripts]# echo $2
handsome
[root@web01 /server/scripts]# echo $3
oldboy
[root@web01 /server/scripts]# echo $#
3
[root@web01 /server/scripts]# echo $@
I am handsome oldboy
[root@web01 /server/scripts]# echo $*
I am handsome oldboy
[root@web01 /server/scripts]# for i in "$*";do echo $i;done
I am handsome oldboy
[root@web01 /server/scripts]# for i in "$@";do echo $i;done
I am
handsome
oldboy
2、shell的进程特殊状态变量说明:
$? 获取执行上一个指令的执行状态返回值(0为成功,非0为失败),这个变量最常用
$$ 获取执行的shell脚本的进程号(PID),这个变量最常用
$! 获取上一个在后台工作的进程的进程号(PID),这个变量不常用
$_ 获取在此之前的命令或脚本的最后一个参数,这个变量不常用
命令:
tee命令:从标准输出到输出 从标准输入到输入
#echo oldboy|tee /tmp/a.log 即输出oldboy 又输入到文件
wc命令
-l 显示行数
-L 显示字符串的个数
3、shell变量的子串
案列:
[root@web01 /server/scripts]# OLDBOY="I am wangyun"
[root@web01 /server/scripts]# echo ${OLDBOY}
I am wangyun
[root@web01 /server/scripts]# echo ${#OLDBOY} <<--#获取变量的长度(个数)
12
[root@web01 /server/scripts]# echo ${OLDBOY:2:2}
am
[root@web01 /server/scripts]# echo ${OLDBOY:2:3}
am
[root@web01 /server/scripts]# echo ${OLDBOY:0:3}
I a
[root@web01 /server/scripts]# echo ${OLDBOY:0:6}
I am w
[root@web01 /server/scripts]# echo ${OLDBOY:5:6}
wangyu
shell变量的子串说明:
${parameter} 返回变量$parameter的内容
${#parameter} 返回变量$parameter内容的长度(按字符),也适合特殊变量
${parameter:offset} 在变量${parameter}中,从位置offset之后开始提取子串到结尾
${parameter:offset:length} 在变量${parameter}中,从位置offset之后开始提取长度为length的子串
删除:
${parameter#word} 从变量${parameter}【开头】开始删除最【短】匹配的word子串
${parameter##word} 从变量${parameter}【开头】开始删除最【长】匹配的word子串
${parameter%word} 从变量${parameter}结尾开始删除最短匹配的word子串
${parameter%%word} 从变量${parameter}结尾开始删除最长匹配的word子串
[root@web01 /server/scripts]# OLDBOY=abcABC123ABCabc
[root@web01 /server/scripts]# echo $OLDBOY
abcABC123ABCabc
[root@web01 /server/scripts]# echo ${OLDBOY#a*C} #---从开头删除最短匹配的子串
123ABCabc
[root@web01 /server/scripts]# echo ${OLDBOY##a*C} #---从开头删除最长匹配的子串
abc
[root@web01 /server/scripts]# echo ${OLDBOY%a*C}
abcABC123ABCabc
[root@web01 /server/scripts]# echo ${OLDBOY%a*c} #---从结尾删除最短匹配的子串
abcABC123ABC
[root@web01 /server/scripts]# echo ${OLDBOY%%a*c} #---从结尾删除最长匹配的子串
#---删空了
删除小结:
#表示从开头删除匹配最短。
##表示从开头删除匹配最长。
%表示从结尾删除匹配最短。
%%表示从结尾删除匹配最长。
a*c表示匹配的字符串, *匹配所有,a*c匹配开头为a中间任意多个字符结尾为c的。
a*C表示匹配的字符串, *匹配所有,a*C匹配开头为a中间任意多个字符结尾为C的。
替换:(类似sed替换)
${parameter/pattern/string} 使用string代替第一个匹配的pattern
${parameter//pattern/string} 使用string代替所有匹配的pattern
[root@web01 /server/scripts]# OLDBOY="I am oldboy,yes,oldboy"
[root@web01 /server/scripts]# echo ${OLDBOY/oldboy/oldgirl}
I am oldgirl,yes,oldboy
[root@web01 /server/scripts]# echo ${OLDBOY//oldboy/oldgirl}
I am oldgirl,yes,oldgirl
[root@web01 /server/scripts]# oldboy=`echo ${OLDBOY//oldboy/oldgirl}`
[root@web01 /server/scripts]# echo $oldboy
I am oldgirl,yes,oldgirl
替换小结:
一个 / 表示替换匹配的第一个字符串
两个 / 表示替换匹配的所有字符串
获取变量内容长度的方法:
[root@web01 /server/scripts]# echo $OLDBOY|wc -L
22
[root@web01 /server/scripts]# echo ${#OLDBOY}
22
[root@web01 /server/scripts]# expr length "$OLDBOY"
22
[root@web01 /server/scripts]# echo $OLDBOY|awk '{print length}'
22
[root@web01 /server/scripts]# echo $OLDBOY|awk '{print length($0)}'
22
3、shell的特殊扩展变量说明:
1)${parameter:-word}:
如果parameter变量值为空或未赋值,就会返回word字符串替代变量的值。(主胎不在家,备胎启用)
用途:如果变量未定义,则返回备用的值,防止变量为空值或未定义而导致异常。
[root@web01 /server/scripts]# test=oldboy
[root@web01 /server/scripts]# echo $test
oldboy
[root@web01 /server/scripts]# result=${test:-unset}
[root@web01 /server/scripts]# echo $result
oldboy
[root@web01 /server/scripts]# unset test
[root@web01 /server/scripts]# echo $test
[root@web01 /server/scripts]# result=${test:-unset}
[root@web01 /server/scripts]# echo $result
unset
2)${parameter:=word}:
如果parameter变量值为空或未赋值,就设置这个变量值为word,并返回其值。位置变量和特殊变量不适用。(主胎不在家,备胎启用并转正)
用途:基本同上一个${test:-unset} ,但是又额外给test变量赋值了。
3)${parameter:?word}:
如果parameter变量值为空或未赋值, word字符串将被作为标准错误输出,否则输出变量的值。
用途:用于捕捉由于变量未定义而导致的错误,并退出程序。
4)${parameter:+word}:
如果parameter变量值为空或未赋值,则什么都不做,否则word字符串替代变量的值。
4、shell中常见的算术运算命令:(整数运算)
1)、(()) 用于整数运算的常用运算符,效率很高(推荐用)
[root@web01 /server/scripts]# a=10
[root@web01 /server/scripts]# ((a=a+1))
[root@web01 /server/scripts]# echo $a
11
2)、let 用于整数运算,类似(())
[root@web01 /server/scripts]# a=10
[root@web01 /server/scripts]# ((a=a+1))
[root@web01 /server/scripts]# echo $a
11
3)、expr 可用于整数运算,但还有很多其他的额外功能
[root@web01 /server/scripts]# a=10
[root@web01 /server/scripts]# expr $a + 111
121
[root@web01 /server/scripts]# b=`expr $a + 111`
[root@web01 /server/scripts]# echo $b
121
4)、$[] 用于整数运算
[root@web01 /server/scripts]# a=11
[root@web01 /server/scripts]# echo $[$a+11]
22
[root@web01 /server/scripts]# echo $[a+11]
22
[root@web01 /server/scripts]# c="$[a+11]"
[root@web01 /server/scripts]# echo $c
22
5)、declare 定义变量值和属性,-i 参数可以用于定义整形变数,做运算
[root@web01 /server/scripts]# a=8
[root@web01 /server/scripts]# declare -i a=a+10
[root@web01 /server/scripts]# echo $a
18
整数或小数运算:(scale= 可以保留小数位)(bc 的几次方是^号)
1)、bc Linux下的一个计算器程序,(适合整数及小数运算)(bc 几次方是^号)
[root@web01 /server/scripts]# echo 1+2|bc
3
[root@web01 /server/scripts]# echo 1.1*2|bc
2.2
[root@web01 /server/scripts]# echo 3/2|bc
1
[root@web01 /server/scripts]# echo 3%2|bc
1
[root@web01 /server/scripts]# echo 3.33*9.99|bc
33.26
[root@web01 /server/scripts]# echo "scale=4;3.33*9.99"|bc
33.2667
[root@web01 /server/scripts]# echo 3^2|bc
9
2)、awk 既可以用于整运算,也可以用于小数运算
[root@web01 ~]# echo 1.1 2|awk '{print $1*$2}'
2.2
[root@web01 ~]# echo 1.1 2|awk '{print $1%$2}' #---除不动,原数返回
1.1
[root@web01 ~]# echo 4 2|awk '{print $1%$2}'
0
expr功能:
1)、计算
[root@web01 /server/scripts]# expr 10 + 1
11
2)、获取字符串长度
[root@web01 /server/scripts]# a="wangyun"
[root@web01 /server/scripts]# expr length $a
7
3)、判断字符串是否为整数数字或字符
[root@web01 /server/scripts]# a=1
[root@web01 /server/scripts]# expr $a + 1 &>/dev/null
[root@web01 /server/scripts]# echo $?
0
[root@web01 /server/scripts]# a=oldboy
[root@web01 /server/scripts]# expr $a + 1 &>/dev/null
[root@web01 /server/scripts]# echo $?
2
4)、用来判断文件的扩展名是否符合指定扩展名
[root@web01 /server/scripts]# cat judge.sh
if expr "$1" : ".*\.avi$" >/dev/null ; then
echo "好兴奋啊"
else
echo "好失望啊"
fi
[root@web01 /server/scripts]# sh judge.sh oldboy.avi
好兴奋啊
[root@web01 /server/scripts]# sh judge.sh oldboy.log
好失望啊
5、shell中常见的算术运算符号:
+、- 加法、减法
*、/、%、 乘法、除法、余数(就是除法剩余的数字)
** 幂运算(就是几次方)
++、-- 增加及减少,可前置也可放在变量结尾,默认步长为1
!、&&、|| 逻辑非(取反)、逻辑与(and)、逻辑或(or)
==、!=、= 比较符号(相等、不相等、对于字符串"="也可以表示相等)
<、<=、>、>= 比较符号(小于、小于等于、大于、大头等于)
<<、>> 向左移位、向右移位
~、|、&、^ 按位取反、按位异或、按位与、按位或
=、+=、-=、*=、/=、%= 赋值运算符,例如a+=1 相当a=a+1,a-=1相当a=a-1
6、read命令基础(是Linux内置命令)
语法:read
参数:
-p prompt 设置提示信息
-t timeout 设置输入等待的时间,单位默认位秒
rea读入的本质就是给变量赋值,知识多了个交互式提示而已
变量赋值的三种方式:
1)定义式a=1
2) read读入式
read -t 10 -p "请输入两个数字: " n m
n=110 m=100
3)脚本传参
$1-100
案例:实现read的基本读入功能
[root@web01 /server/scripts]# read -t 10 -p "Pls input one num:" num
#---读入一个输入,赋值给num变量,注意num前有空格
Pls input one num:18 #---输出数字18,相当于把18赋值给num变量
[root@web01 /server/scripts]# echo $num #---输出变量值
18
[root@web01 /server/scripts]# read -p "please input two number:" a1 a2
#---读入两个输入,注意要以空格隔开,分别赋值给a1和a2变量,a1前后都要有空格
please input two number:1 2
[root@web01 /server/scripts]# echo $a1
1
[root@web01 /server/scripts]# echo $a2
2
练习:
01-dingyi.sh
a=2
b=6
echo "a-b=$(($a-$b))"
echo "a+b=$(($a+$b))"
echo "a*b=$(($a*$b))"
echo "a/b=$(($a/$b))"
echo "a**b=$(($a**$b))"
echo "a%b=$(($a%$b))"
变通:02-read.sh
改成read读入两个数(sh 02-read.sh)"请输入两个整数:"6 2
[root@web01 /server/scripts]# cat 02-read.sh
read -p "请输入两个整数:" a b
echo "a-b=$(($a-$b))"
echo "a+b=$(($a+$b))"
echo "a*b=$(($a*$b))"
echo "a/b=$(($a/$b))"
echo "a**b=$(($a**$b))"
echo "a%b=$(($a%$b))"
变通2:03-chuancan.sh
改成命令行传入两个数 (sh 03-chuancan.sh 6 2)
[root@web01 /server/scripts]# cat 03-chuancan.sh
a=$1
b=$2
echo "a-b=$(($a-$b))"
echo "a+b=$(($a+$b))"
echo "a*b=$(($a*$b))"
echo "a/b=$(($a/$b))"
echo "a**b=$(($a**$b))"
echo "a%b=$(($a%$b))"
语法:test(是个内置命令)
参数:
-f 用于测试文件是否为普通文件
-x 用于测试文件是否有执行权限
- n字符串
字符串的长度非零
字符串等价于-n字符串
- z的字符串
字符串的长度为零
- f文件
文件存在,并且是一个常规文件
- d文件
文件存在,并且是一个目录
- e文件
文件是否存在
- L文件
文件存在,是一个符号链接(与-h相同)
- x文件
文件存在并授予执行(或搜索)权限
- r文件
文件存在,并授予读权限
- b文件
文件存在并且是块特殊的
- c文件
文件存在并且是字符特殊的
- g的文件
文件存在,并且是set-group id
- G的文件
文件存在,并由有效组ID拥有
- h文件
文件存在,是一个符号链接(与-L相同)
- k文件
文件存在并设置了它的粘性位
- O文件
文件存在,并由有效用户ID拥有
- p文件
文件存在,并且是一个命名管道
- s文件
文件存在且大小大于零
- S文件
文件存在,并且是套接字
-t 文件
在终端上打开FD文件描述符
- u文件
文件存在,并设置其set-user- id位
- w文件
文件存在,并授予写权限
文件测试表达式用法:对文件的属性进行判断,然后根据结果进行处理
[root@web01 /server/scripts]# touch oldboy.txt
[root@web01 /server/scripts]# [ -f oldboy.txt ] && echo 1 || echo 0
1
[root@web01 /server/scripts]# rm -f oldboy.txt
[root@web01 /server/scripts]# [ -f oldboy.txt ] && echo 1 || echo 0
0
[root@web01 /server/scripts]# mkdir oldboy
[root@web01 /server/scripts]# [ -f oldboy ] && echo 1 || echo 0
0
[root@web01 /server/scripts]# [ -e oldboy ] && echo 1 || echo 0
1
[root@web01 /server/scripts]# [ -d oldboy ] && echo 1 || echo 0
1
[root@web01 /server/scripts]# [ -L oldboy ] && echo 1 || echo 0
0
字符串表达式:
[root@web01 /server/scripts]# a="oldboy"
[root@web01 /server/scripts]# [ -z "$a" ] && echo 1 || echo 0
0
[root@web01 /server/scripts]# unset a
[root@web01 /server/scripts]# echo $a
[root@web01 /server/scripts]# [ -z "$a" ] && echo 1 || echo 0
1
[root@web01 /server/scripts]# [ "$a" = "oldboy" ] && echo 1 || echo 0
0
[root@web01 /server/scripts]# a="oldboy"
[root@web01 /server/scripts]# [ "$a" = "oldboy" ] && echo 1 || echo 0
1
[root@web01 /server/scripts]# [ "$a" = "oldgir" ] && echo 1 || echo 0
0
[root@web01 /server/scripts]# b="oldgirl"
[root@web01 /server/scripts]# [ "${#a}" = "${#b}" ] && echo 1 || echo 0
0
[root@web01 /server/scripts]# b="oldgir"
[root@web01 /server/scripts]# [ "${#a}" = "${#b}" ] && echo 1 || echo 0
1