一.shell变量概述
变量是shell传递数据的一种方法,即用一个固定的字符串去表示不固定的值,便于后期引用
二.变量命名规范
命名要求:字母、数字、下划线组成,字母开头(不能数字开头)
变量名尽量具备一定含义,但不要和系统命令冲突;等号赋值,两边不能空格 例1: ip=192.168.1.100 #不要和已有的系统命令冲突 HostName_Ip=192.168.1.100 #推荐驼峰式命名
例1
HostName=$(hostname) echo $HostName
三.shell变量定义的方式
用户自定义变量:人为定义变量名称 系统环境变量:系统操作环境相关数据 位置参数变量:向脚本传递参数,名称固定,作用固定 预定义变量:bash定义好的变量,名称固定,作用固定
1、用户自定义变量,当前shell有效
(1) 变量名不能出现"-"横杠,变量值有空格需要引号括起来
var="hello world"
(2) 引用变量,$变量名 或 ${变量名}
echo $var echo $var_log #变量无法引用 echo ${var}_log #变量可以引用
(3) 查看变量,set显示所有变量(自定义和环境变量)
set | grep var
(4) 取消变量,作用范围:当前shell
unset var
(5) 引用变量,"" 双引号属于弱引用,‘’单引号属于强引用
echo "$var hello china" #需要引用变量值 echo '$var hello china' #只想引用变量名,不执行$特殊符号 echo "$var hello china \$SHELL" #部分变量执行,部分变量不执行
(6) 变量命令赋值,使用或$() ***
不能嵌套{ ``` } $() 能嵌套 ${ ${ }}
Ip=`ifconfig ens33 | grep "inet" |grep -v inet6 |awk '{print $2}'` 或 Ip=$(ifconfig ens33 | grep "inet" |grep -v inet6 |awk '{print $2}')
2、系统环境变量
(1) 使用系统已定义好的变量
export echo "命令目录:$PATH" 永久将脚本加入到全局变量 PATH=${PATH}:/sh export PATH=${PATH}:/sh echo "export PATH=${PATH}:/sh" >> /etc/profile echo "宿主目录: $HOME" echo "当前目录: $PWD" echo "主机名: $HOSTNAME" echo "客户端地址和端口: $SSH_CONNECTION"
(2) 自定义环境变量
export var2 #把局部变量发布到全局,子shell也识别
var2="hello beijing" #定义局部变量,子shell不识别 cat >> env1.sh << EOF #!/bin/bash echo $var2 EOF sh env1.sh
3、 预定义变量
vim variable.sh
#!/bin/bash echo
"当前shell脚本的文件名:$0"
echo "第1个shell脚本位置参数:$1"
echo "第2个shell脚本位置参数:$2"
echo "第3个shell脚本位置参数:$3"
echo "第10个shell脚本位置参数:${10}"
echo "所有传递的位置参数:$"
echo "所有传递的位置参数:$@"
echo "总共传递的参数数量:$#"
echo "当前程序运行的PID:$$"
echo "上一个命令执行的返回结果:$?"
例:
$* 和 $@ 的区别: ** 不加引号两者结果相同;加引号,$*把参数作为整体,$@把参数作为分散个体。 vim variable2.sh #!/bin/bash test() { echo "未加引号,两者相同" echo $* echo $@ echo "添加引号,两者对比" echo "----"\$*----"" for I in "$*" do echo $I done echo "----"\$@----"" for I in "$@" do echo $I done } test 11 22 33 44 sh variable2.sh
4、 位置变量是预定义变量的一部分,是定义脚本后的参数位置的
$1 $2 $3 . . $9 ${10}
5补充:将命令执行结果传给变量(命令替换)
例1:打印今年和明年的时间
echo "今年是 $(date +%Y) 年" echo "明年是 $(($(date +%Y)+1)) 年"
例2:命令的嵌套使用
1. Back=$(tar zcf /backup/root.tar.gz $(find /root/ -name "*.txt")) 2. echo $Back
6、shell变量赋值
除了自定义和环境变量,还可以使用read进行交互式传递变量
例1:
vim read1.sh #!/bin/bash read -p "请输入备份的目录:" Dir echo "你要备份的目录是: $Dir"
echo "-----backuping $Dir-----" echo "-----backup $Dir done-----" sh read1.sh
例2:
vim read2.sh #!/bin/bash back_dir1=/backup read -p "请输入你的备份目录:" back_dir2 echo $back_dir1 echo $back_dir2
例3:
vim read3-2.sh *** #!/bin/bash IP=192.168.8. for i in {1..254} do ping -w 1 -c 1 ${IP}$i &> /dev/null if [ $? -eq 0 ];then echo -e "\033[32m ${IP}$i 可以通信 \033[0m" else echo -e "\033[31m ${IP}$i 不可通信 \033[0m" fi done
例4:使用read修改主机名和ip
vim read4.sh #!/bin/bash read -p "请输入你想修改的主机名:" HostName read -p "你确定要修改如下内容,[Y|N]" RC if [ $RC == "Y" ];then hostnamectl set-hostname $HostName else exit fi
四.shell变量替换
${变量#匹配规则} 从头开始匹配,最短删除
${变量##匹配规则} 从头开始匹配,最长删除
${变量%匹配规则} 从尾开始匹配,最短删除
${变量%%匹配规则} 从尾开始匹配,最长删除
${变量/旧字符串/新字符串} 替换字符串,仅替换第一个
${变量//旧字符串/新字符串} 替换字符串,替换全部
从前往后删变量内容
Qh_url=mirrors.tuna.tsinghua.edu.cn echo $Qh_url echo ${Qh_url#*.} #删除.分隔的第一个字段 echo ${Qh_url##*.} #仅保留最后一个字段
从后往前删变量内容
Qh_url=mirrors.tuna.tsinghua.edu.cn echo $Qh_url echo ${Qh_url%.*} #删除最后一个字段 echo ${Qh_url%%.*} #仅保留第一个字段
变量内容替换
Qh_url=mirrors.tuna.tsinghua.edu.cn echo $Qh_url echo ${Qh_url/u/U} echo ${Qh_url//u/U}
五.shell变量运算
1.整数运算,expr、$(())、$[],不支持小数运算
a+b 加
a-b 减
a*b 乘(expr计算时,用 \* )
a/b 除
a%b 余
例子1:
a=20 b=10 expr $a + $b echo $(( $a + $b )) echo $[ $a + $b ]
例2:递增和递减
echo $((a++)) echo $((a--)) echo $((++b)) echo $((--b)) echo $((100*(1+100)/2)) 求1到100之和
小数运算,bc工具
2. yum -y install bc echo "2*4" |bc echo "2^4" |bc echo "scale=2;3/2" |bc awk 'BEGIN{print 3/2}'
六.流程控制语句if
1. 单分支语句
1. if [ 满足条件 ];then 2. 执行代码 3. fi
例:
vim if1.sh #!/bin/bash if [ while 1>0 ];then echo "ok" fi
2.双分支语句
if [ 满足条件 ];then 执行代码 else 执行另一条代码 fi
例:
vim if2.sh #!/bin/bash if grep "$1" /etc/passwd;then echo "ok" else echo "error" fi sh if2.sh root sh if2.sh wangwu
3.多分支语句,逐条匹配,匹配即执行
if [ 满足条件1 ];then 执行代码1 elif [ 满足条件2 ];then 执行代码2 else 执行最后代码 fi
例:
vim if3.sh #!/bin/bash read -p "请输入用户名:" User if grep $User /etc/passwd &> /dev/null;then echo "用户$User存在" elif ls -d /home/$User &> /dev/null;then echo "用户$User不存在" echo "但是$User宿主目录存在" else echo "用户$User不存在" echo "$User宿主目录也不存在" fi
扩展:
> 正确输出 >> 追加输出重定向
2> 错误输出 2>> 错误追加输出重定向
&> 混合输出 &>> 混合追加输出