shell脚本变量详解(自定义变量、环境变量、变量赋值、变量运算、变量内容替换)

shell变量

shell变量是指用一个特定的字符串去表示不固定的内容

1.变量的类型

1.1自定义变量

一般情况下不怎么使用环境变量,如果需要在其他文件中引入某个文件的变量则在脚本最开始的位置使用source 或者. 执行下该脚本即可

shell脚本变量详解(自定义变量、环境变量、变量赋值、变量运算、变量内容替换)_第1张图片
​ 定义变量:变量名=变量值 变量名必须以字母或下划线开头,区分大小写 ip1=127.0.0.1

​ 引用变量:$变量名 或 变 量 名 ( “ ” 花 括 号 另 有 他 意 , 假 如 想 在 变 量 后 面 直 接 加 其 他 内 容 , 这 是 用 花 括 号 会 非 常 方 便 , 同 时 也 有 很 多 功 能 , 例 如 {变量名} (“{}”花括号另有他意,假如想在变量后面直接加其他内容,这是用花括号 会非常方便,同时也有很多功能,例如 便{#变量名}则会输出这个变量的长度)

​ 查看变量:echo $变量名 set(会列出所有变量,包括自定义变量和环境变量)

​ 取消变量:unset 变量名

​ 作用范围:仅在当前shell中有效

​ 自己写的几个脚本

1.1.不使用变量

#!/bin/bash
ping -c3 www.baidu.com &>/dev/null && echo "www.baidu.com is up" ||echo  "www.baidu.com is down"

1.2.使用变量,用特殊符号一行去进行条件测试

#!/bin/bash
IP=www.baidu.com
ping -c3 $IP &>/dev/null && echo "$IP is up" || echo "$IP is down"

1.3.使用if语句做判断

#!/bin/bash
COM=www.baidu.com
if ping -c3 $COM &>/dev/null ;then
echo "$COM is up"
else	
echo "$COM is down"
 fi

1.4.使用条件测试

#!/bin/bash
COM=www.baidu.com
ping -c3 $COM &>/dev/null
if [ $? -eq 0 ];then
echo "$COM is up"
else
echo "$COM is down"
fi

1.5.不适用固定的变量值而是用read命令从键盘获取变量值

#!/bin/bash
read -p "please input a ip: " ip
ping -c3 $ip &>/dev/null
if [ $? -eq 0 ] ; then
echo "$ip is up"
else
echo "$ip is down"

1.2.环境变量

​ 定义环境变量:方法一 export back_dir=/home/backup

​ 方法二 export back_dir 将自定义变量转换成环境变量

​ 引用环境变量:$变量名 或 ${变量名}

​ 查看环境变量 :echo $变量名 env 例如:env | grep back_dir

​ 变量作用范围:在当前shell和子shell有效

1.3.位置变量

​ $1 $2 $3 $4 $5 $6 $7 $8 $9 ${10}

1.4.预定义变量

​ $0 脚本名称 默认输出路径加脚本名,可以使用basename来只输出脚本的名称不包含路径,dirname可以输出脚本所在的文件夹名称

​ $* 所有的参数

​ $@ 所有的参数

​ $# 参数的个数

​ $$ 当前进程的PID

​ $! 上一个后台进程的PID

​ $? 上一个命令的返回值,0表示成功

∗ 和 *和 @的区别

​ $*:所有的位置参数被作为一个单词,注意 $* 必须被双引号引用

@ : 与 @:与 @*同义,但每个参数都是一个独立的""引用字串,这就意味着参数被完整地传递

​ $@ $* 只在被双引号包起来的时候才会有差异
​ 双引号括起来的情况:
​ $*将所有的参数认为是一个字段
​ $@以IFS(默认为空格)来划分字段,如果空格在“”里面,不划分。采用LS的脚本运行./test 1 “2 3” 4 来发现差异

​ 没有括起来的情况是 @ 和 @和 @*一样的,见到IFS就划分字段。还是采用LS的脚本运行./test 1 “2 3” 4 来发现差异

1.4.1预定义变量使用脚本

#!/bin/bash
echo "第2个位置参数是$2"
echo "第1个位置参数是$2"
echo "第4个位置参数是$2"

echo "所有参数是: $*"
echo "所有参数是: $@"
echo "参数的个数是: $#"
echo "当前进程的PID是:$$"

echo '1='$1
echo '$2='$2
echo '$3='$3
echo '$*='$*
echo '$@='$@
echo '$#='$#
echo '$$='$$

1.4.2预定义变量位置变量整合脚本

#!/bin/bash
if [ $# -eq 0 ];then
        echo "usage: `basename $0` file"
        exit

fi
if [ ! -f $1 ];then
        echo "error file"
        exit
fi

for ip in `cat $1`
do
        ping -c1 $ip &>/dev/null
        if [ $? -eq 0 ];then
                echo "$ip is up"
        else
                echo "$ip is down"
        fi
done

1.4.3预定义变量批量创建用户

#!/bin/bash
#-----------批量创建用户------------
if [ $# -eq 0 ];then
        echo "usage: `basename $0` file"
        exit
fi

if [  -f $1 ];then
        echo "Began to create a file of the user...."
else
        echo "error file"
fi

for user in `cat user.txt`
do
        useradd $user
        if [ $? -eq 0 ];then
                echo "123" |passwd --stdin $user
        fi
done

2.变量的赋值方式:

2.1.显示赋值

​ 变量名=变量值

​ 实例:

	ip1=192.168.81.250

	school="beijing 1000phone"

	today1=$(date +%F) 或者使用反引号

2.2.read从键盘读入变量值

	read 变量名

	read -p "提示信息:"  变量名

	read -t 5 -p "提示信息:"  变量名			-t代表等待时间,5秒内不输入则退出

	read -n 2 变量名		-n代表限制输入的字符数
	

​ read后面可以跟很多变量,例如下图,根据空格将对应的变量赋值 [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ESrnCtnb-1590841971204)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20200128205106658.png)]

定义或引用变量时注意事项

“” 弱引用 ""双引号中可用使用变量

‘’ 强引用 ''单引号中不可用变量,单引号中输入的啥输出就是啥

很多情况下使用嵌套

例如: name=“jiang xiaolong” ; boy="$name"’ is good!’;echo $boy

`` 命令替换,等价于$()反引号中的shell命令会先被执行

3.变量的运算

3.1.整数运算

方法一:expr

expr	1+2

expr $num1 + $num2		+ - \\* / %

方法二:$(())

echo $(($num1+$num2))		+ - * / %
echo $((num1+num2))		可用省略括号内的$符号
echo $((5-3*2))		也可以直接用数值进行运算
echo $(((5-3)*2))		第三个括号是数值的简便算法运算
echo $((2**3))			也可以使用整数幂运算
sum=$((1+2));echo $sum		可用赋给变量

#---------------求磁盘使用率---------------------
disk_gen=$(df | grep -v "^文件" |grep '/$'|awk '{print $6}')
disk_gen_used=$(df | grep -v "^文件" |grep '/$'|awk '{print $3}')
disk_gen_total=$(df | grep -v "^文件" |grep '/$'|awk '{print $2}')
disk_gen_percent=$(($disk_gen_used*100/$disk_gen_total))
echo "disk usage rate is $disk_gen_percent"'%'

disk_myscr=$(df | grep -v "^文件" |grep '/my_scripts$'|awk '{print $6}')
disk_myscr_used=$(df | grep -v "^文件" |grep '/my_scripts$'|awk '{print $3}')
disk_myscr_total=$(df | grep -v "^文件" |grep '/my_scripts$'|awk '{print $2}')
disk_myscr_percent=$(($disk_myscr_used*100/$disk_myscr_total))
echo "disk usage rate is $disk_myscr_percent"'%'


if [ $disk_gen_percent -ge 80 ];then
        echo '/磁盘使用率超过80%'
elif [ $disk_myscr_percent -ge 80 ];then
        echo "my_scripts磁盘使用率超过80%"
fi

方法三:$[]

​ 使用方法和方法二类似,只不过括号少了

echo $[5+2]					+ - * / %
echo $[5**2]

#-----------------求出内存使用率------------
mem_used=`free -m | grep '^Mem:'|awk '{print $3}'`
mem_total=`free -m | grep '^Mem:'|awk '{print $2}'`
mem_percentage=$[$mem_used*100/$mem_total]
echo "Memory usage rate is $mem_percentage"'%'
if [ $mem_percentafe > 80 ];then
        echo "系统内存使用率超过了80%"
else
        echo "ok"
fi

方法四:let

​ while循环常用到

let sum=2+3;echo $sum

let i++;echo $i			i++表示i=i+1

#------------------let方法运算---------------
ip=127.0.0.1
i=1
while [ $i -le 5 ]
do
        ping -c1  $ip &>/dev/null
        if [ $? -eq 0 ];then
                echo "$ip is up..."
        fi
        let i++
done

3.2.小数运算

echo "2*4"|bc
echo "2^4"|bc
echo "scale=2;6/4"|bc			scale不可更换成别的,固定参数
awk 'BEGIN{print 1/2}'
echo "print 5.0/2" | python

4.变量内容的删除和替换

4.1.内容的删除

​ 总结:

​ 原变量内容不会修改

​ *.表示.之前的所有内容

​ #表示删除到第一个匹配的内容,##表示一直删除到最后一个匹配的内容

4.1.1.从前往后删

url=www.sina.com.cn

echo ${#url}		显示出变量的长度

echo ${url}	标准查看

echo ${
     url#*.}		从前往后删,删完第一个.之前的所有内容,最短匹配

		输出:sina.com.cn

echo ${
     url##*.}	从前往后删一直删到最后一个包含.的内容,最长匹配

		输出:cn

[root@192 d02章_Shell变量精讲]# echo ${url}
	www.baidu.com.cn
[root@192 d02章_Shell变量精讲]# echo ${url#www.}
	baidu.com.cn
[root@192 d02章_Shell变量精讲]# echo ${url#www.baidu}
	.com.cn
[root@192 d02章_Shell变量精讲]# echo ${url#www.bai}
	du.com.cn
[root@192 d02章_Shell变量精讲]# echo ${url##www.baidu}
	.com.cn
[root@192 d02章_Shell变量精讲]# echo ${url##www.baidu.com}
	.cn
[root@192 d02章_Shell变量精讲]# echo ${url##*.}
	cn

4.1.2.从后往前删

url=www.sina.com.cn
echo ${url}
echo ${url%.*}		从后往前,最短匹配,删除最后包含.的内容
		输出:www.sina.com
echo ${url%%.*}		从后往前,最长匹配,贪婪匹配,删到最前面包含.的内容
		输出:www

[root@192 d02章_Shell变量精讲]# echo ${url}
www.baidu.com.cn
[root@192 d02章_Shell变量精讲]# echo ${url%.*}
www.baidu.com
[root@192 d02章_Shell变量精讲]# echo ${url%%.*}
www
[root@192 d02章_Shell变量精讲]# echo ${url%%.baidu.com.cn}
www
[root@192 d02章_Shell变量精讲]# echo ${url%%.*}
www
[root@192 d02章_Shell变量精讲]# echo ${url%.cn}
www.baidu.com
[root@192 d02章_Shell变量精讲]# echo ${url%.baidu.cn}
www.baidu.com.cn

4.1.3.从前往后/从后往前再次练习

[root@192 d02章_Shell变量精讲]# echo ${aaa}
jiangxiaolonga
[root@192 d02章_Shell变量精讲]# echo ${aaa%g}		错误,应该是{aaa%g*或者aaa%ga或者*g*},因为g不是最后一个字符
jiangxiaolonga
[root@192 d02章_Shell变量精讲]# echo ${aaa%ga}
jiangxiaolon
[root@192 d02章_Shell变量精讲]# echo ${aaa%a}
jiangxiaolong
[root@192 d02章_Shell变量精讲]# echo ${aaa#a}		错误,应该是{aaa#*a或者aaa#jia或者aaa#*a*},因为a不是最前面的字符
jiangxiaolonga
[root@192 d02章_Shell变量精讲]# echo ${aaa#jia}
ngxiaolonga
[root@192 d02章_Shell变量精讲]# echo ${aaa#*a}
ngxiaolonga
[root@192 d02章_Shell变量精讲]# echo ${aaa##*ao}
longa
[root@192 d02章_Shell变量精讲]# echo ${aaa%a}
jiangxiaolong
[root@192 d02章_Shell变量精讲]# echo ${aaa%longa}
jiangxiao
[root@192 d02章_Shell变量精讲]# echo ${aaa%%xiao*}
jiang
[root@192 d02章_Shell变量精讲]# echo ${aaa%%*xiao*}

4.2.索引及切片

变量值的每一个字符代表一个索引,从0开始

url=www.sina.com.cn
	0123456789.....		索引位
echo ${url:0:5}		取0-5的索引位进行切片,切出www.s
echo ${url:5:5}		取第五位到第五位
echo ${url:5}		取第五位到最后

4.3.内容的替换

url=www.sina.com.cn
echo ${url/sina/baidu}		将sina替换成baidu
echo ${url/n/N}			只将第一个n替换成N
echo ${url//n/N}		贪婪匹配,将所有的n替换成N

#-----------利用替换来求磁盘使用率-----------
cpgzd=/
gen=`df | grep $cpgzd'$'|awk '{print $6}'`
myscripts=`df | grep ${
      cpgzd/'/'/my_scripts}'$'| awk '{print $6}'`		因为是/所有要把他用强引用引起来取消转义内容
gen_used=`df | grep $cpgzd'$'|awk '{print $3}'`
myscripts_used=`df | grep ${
      cpgzd/'/'/my_scripts}'$'| awk '{print $3}'`
gen_total=`df | grep $cpgzd'$'|awk '{print $2}'`
myscripts_total=`df | grep ${
      cpgzd/'/'/my_scripts}'$'|awk '{print $2}'`
gen_percen=$(($gen_used*100/$gen_total))
myscripts_percen=$(($myscripts_used*100/myscripts_total))
echo "/ disk usage rate is $gen_percen"'%'
echo "my_scripts disk usage rate is $myscripts_percen"'%'

4.4.变量的替代

unset var1
echo ${var1}
echo ${var1-aaaaa}			-表示替代的变量值
	aaaaa
var2=111
echo ${var2-bbbbb}
	111
var3=
echo ${var3-ccccc}${变量名-新的变量值}
变量名没有被赋值:会使用新的变量值替代
变量名有被赋值(包括空值):不会被替代

4.1空值的变量无法被替代很不合理

​ 可以使用:-的形式让空值的变量得到替代

unset var1
unset var2
unset var3
var2=
var3=111
echo ${var1:-aaaaa}		被替代
echo ${var2:-bbbbb}		被替代
echo ${var3:-ccccc}		不会替代

${变量名:-新的变量值}
变量没有被赋值(包括控制):都会使用“新的变量值”替代
变量有被赋值:不会被替代
就好比var1单身可以有对象,var2分过手可以再次拥有对象,var3有对象不能被插足

扩展

unset var1
unset var2
unset var3
var2=111
var3=
echo ${var2+aaaa}		定义过的会被修改
echo ${var3+aaaa}		空值的也会被修改
echo ${var1+aaaa}		没有定义变量值的不会被修改

echo ${var2:+aaaa}		定义过的会被修改
echo ${var3:+aaaa}		空值的不会被修改
echo ${var1:+aaaa}		没有定义变量值的不会被修改

echo ${var1=aaaa}		没有定义变量值的会被修改
echo ${var2=aaaa}		定义过的不会被修改
echo ${var3=aaaa}		空值的也会被修改

echo ${var1:=aaaa}		没有定义变量值的会被修改
echo ${var2:=aaaa}		定义过的不会被修改
echo ${var3:=aaaa}		空值的也会被修改

echo ${var1?aaaa}		没有定义变量值的会被修改
echo ${var2?aaaa}		定义过的不会被修改
echo ${var3?aaaa}		空值的也会被修改

echo ${var1?=aaaa}		没有定义变量值的会被修改
echo ${var2?=aaaa}		定义过的不会被修改
echo ${var3?=aaaa}		空值的也会被修改

5.i++和++i

对变量的影响

i=1
let i++
echo $i
	2
j=1
let ++j
echo $j
	2
对变量几乎没影响,输出都一样
	

对表达式的值的影响

unset i
unset j
i=1
j=1
let x=i++		先赋值,在运算		在这里x=,y= 就是表达式
let y=++j		先运算在复制
echo $i		输出2
echo $j		输出2
echo $x		输出1
echo $y		输出2

i++和++i最大的区别在于就是i++是将变量i的值直接赋给新变量名在进行运算而++i是先运算,将运算结果直接赋给新变量名

6.shell中的特殊符号

() 子shell执行例如(ls)

((1>2)) 数值比较,运算

$() 命令替换

$(()) 整数运算

{} 集合,例如touch file{1…2}

${} 变量引用

[] 条件测试,例如[ -d /home -a -f /etc/profile ]

[[]] 条件测试,支持正则=~ 例如 [ [ -d /home && -f /etc/profile ] ]

$[] 整数运算

执行脚本:

​ ./01.sh 需要执行权限在子shell中执行

​ bash 01.sh 不需要执行权限在子shell中执行

​ . 01.sh 在当前shell执行,不需要执行权限

​ source 01.sh 在当前shell执行,不需要执行权限

调试脚本:

​ sh -n 02.sh 仅调试syntax error

​ sh -vx 02.sh 以调试的方式执行,查询整个执行过程

ho $j 输出2
echo $x 输出1
echo $y 输出2

i++和++i最大的区别在于就是i++是将变量i的值直接赋给新变量名在进行运算而++i是先运算,将运算结果直接赋给新变量名

你可能感兴趣的:(shell脚本)