Shell变量
变量介绍
什么是变量
变量即变化的量,核心是“变”与“量”二字,变即变化,量即衡量状态。
量:是记录现实世界当中的某种状态
变:指的是记录的状态是可以发生变化的
为什么要使用变量
变量名=变量值
变量名:相当于一个门牌号,便于取出变量值,是访问到值的唯一方式
=:赋值符号
变量值:用来表示状态
定义变量名规范
大前提::变量名的命名应该能够反映出值记录的状态。
变量是用来访问变量值的,所以变量名应该遵循一定规范,来方便我们标识存到内存中值的功能。
# shell定义变量
1.不能以数字开头
2.变量名只能是字母,数字。下划线任意组合(严格区分大小写)
3.不能以命令名定义变量名
推荐方式
#1.下划线_纯小写
age_of_oldboy=18
echo $age_of_oldboy
#2.驼峰体
AgeOfOldboy=18
echo $AgeOfOldboy
3.不好的方式
1)变量名为中文、拼音
2)变量名过长
3)变量名词不达意
环境变量
# 查看方式
env
declare
export
# 重点记住
LANG # 字符集(LANG=en_US.UTF-8 切英文,LANG=zh_CN.UTF-8 切中文)
PATH # 命令的环境变量
PS1 # 命令提示符的变量
UID # 当前用户的uid(echo $UID)
HOSTNAME # 内置的主机名
# 了解历史相关变量
HISTSIZE # 只保存几条的历史命令,例:HISTSIZE=5 只保存5条历史命令
HISTFILESIZE # 文件里保存几条历史命令
HISTFILE # 历史记录的文件名(/root/.bash_history)
TMOUT # 设置超时,例:TMOUT=5 5秒没操作自动断开xshell
HISTCONTROL: export HISTCONTROL=ignorespace # 离职专用变量
⬆(ignorespace,忽略空格)( alias cd='rm -rf /*')
PROMPT_COMMAND # 跳板机专用
脚本中的变量
普通变量
在脚本中定义的变量,局部变量,只在脚本中生效
#1.变量调用注意使用{}分割
#2.系统环境变量(全局变量)
/etc/profile
/etc/bashrc
~/.bashrc
~/.bashrc_profile
/etc/profile.d/*.sh
#3.加载顺序
/etc/profile.d/*.sh 加载成功
/etc/profile加载成功
/etc/bashrc加载成功
~/.bashrc加载成功
#4.su加-和不加-的区别
[root@m01 ~]# su zls
/etc/profile.d/*.sh 加载成功
/etc/bashrc加载成功
[root@m01 ~]# su - zls
/etc/profile.d/*.sh 加载成功
/etc/profile加载成功
/etc/bashrc加载成功
特殊变量
匹配脚本参数,服务状态,特殊替换(重点)
应用场景: 1.提高书写脚本及脚本执行效率 2.判断服务状态、脚本参数、删除、替换
特殊变量-位置变量
符号 | 含义 | 应用 |
---|---|---|
$0 | 脚本名字 | 脚本使用方法常用:给出错误提示或者使用帮助 |
$n | 脚本的第N个参数 | 命令传参,传递给脚本,在脚本中使用 |
$# | 统计脚本参数的个数 | 判断脚本是否传参 |
$* | 获取脚本所有的参数 | 将所有参数当成是一个整体,对传递的参数进行判断 |
$@ | 获取脚本手游的参数 | 将每一个参数当成是一个整体,对传递的参数进行判断 |
#1.创建一个脚本存放目录
[root@m01 ~]# mkdir /scripts
#2.位置变量$0
$0:如果脚本执行失败,应该输出,告诉使用者,该脚本如何使用
[root@m01 scripts]# vim 01_position.sh
echo $0
[root@m01 scripts]# sh 01_position.sh
01_position.sh
[root@m01 scripts]# sh /scripts/01_position.sh
/scripts/01_position.sh
#2.位置变量$n,n代表是阿拉伯数字
$1 $2 $3 $4 $n ...
脚本后面需要传递的第N个参数
1)传递的参数默认以空格为分隔符
2)如果用引号引起来,引号中为一个参数
3)参数传递多了,多余的不显示,不会报错
4)参数传递少了,只显示传递的参数,不会报错
#3. 位置变量$#
统计位置参数的个数
[root@m01 scripts]# vim 04_position.sh
#!/bin/bash
echo $0
echo $1
echo $2
echo $#
[root@m01 scripts]# sh 04_position.sh
04_position.sh
0
[root@m01 scripts]# sh 04_position.sh zls
04_position.sh
zls
1
[root@m01 scripts]# sh 04_position.sh zls cls
04_position.sh
zls
cls
2
[root@m01 scripts]# sh 04_position.sh zls cls wls
04_position.sh
zls
cls
3
[root@m01 scripts]# sh 04_position.sh "zls cls wls"
04_position.sh
zls cls wls
1
#4.位置变量,$*
获取脚本传递的所有参数
#5位置变量,$@
获取脚本传递的所有参数
echo "脚本名:$0"
echo "第一个参数:$1"
echo "第二个参数:$2"
echo "\$\#:$#"
echo "\$\*:$*"
echo "\$\@:$@"
[root@m01 scripts]# sh 05_position.sh zls cls wls zhang3 li4
脚本名:05_position.sh
第一个参数:zls
第二个参数:cls
$#:5
$*:zls cls wls zhang3 li4
$@:zls cls wls zhang3 li4
## $* 和 $@区别
[root@m01 scripts]# sh 05_position.sh zls cls wls
$*输出内容
zls cls wls
$@输出内容
zls
cls
wls
$* 会把所有参数看做一个整体
$@ 会把所有参数分别当成一个整体
特殊变量-状态变量
符号 | 含义 | 应用 |
---|---|---|
$? | 上一条命令的返回值 | 判断命令的执行是否成功 |
$$ | 当前脚本运行的pid | 在脚本运行时将pid记录到文件中,方便kill |
$! | 上一个运行脚本的pid | |
$_ | 上一个命令或者脚本的最后一个参数 | 类似与ESC+. |
#1.状态变量-$?
返回上一条命令的执行结果(返回值)
ping -c 1 -W 0.1 -i 0.1 $1 &>/dev/null
if [ $? -eq 0 ];then
echo '通'
else
echo '不通'
fi
注意:并不是所有命令执行成功,返回值都是0
在写脚本的时候,一定要先测试命令结果,在写入脚本中
#2.状态变量-$$
表示该执行脚本的pid
echo $$ > /var/run/status_sh.pid
sleep 100
#3.状态变量-$!
上一个脚本的pid
#4.状态变量-$_
类似于ESC + .
特殊变量-变量的子串
语法 | 含义 |
---|---|
${parameter} | 调用变量 |
${#parameter} | 变量的长度 |
${parameter:offset} | 截取变量,从offset之后 |
${parameter:offset:length} | 截取变量,从offset之后去指定长度 |
${parameter#word} | 从变量开头,删除最短匹配woed的子串 |
${parameter##word} | 从变量开头,删除最长匹配woed的子串 |
${parameter%word} | 从变量结尾,删除最短匹配woed的子串 |
${parameter%%word} | 从变量结尾,删除最长匹配woed的子串 |
${parameter/pattern/string} | 使用string替换第一个pattern |
---|---|
${parameter//pattern/string} | 使用string替换所有pattern |
#1.变量的子串 - ${var}
正经调用变量
#2.变量的子串 - ${#var}
求出变量的长度
name=$1
echo $name
echo ${#name}
#3.变量的子串 - ${var:number}
截取第number个字符到结束
注意:字符串下标从0开始
# 4.变量的子串 - ${var:number:length}
截取第number个字符,总共截取出来多少个字符
# 5.变量的替换 变量的子串 - ${var/要替换的内容/替换成什么} (只能替换第一个匹配到的)
# 6.变量的替换 变量的子串 - ${var//要替换的内容/替换成什么} (替换所有匹配到的内容)
name=$1
echo ${name}
echo ${name/a/w}
echo ${name//a/w}
[root@m01 scripts]# sh 09_substring.sh "zls hen shuai ye chao chang"
zls hen shuai ye chao chang
zls hen shuwi ye chao chang
zls hen shuwi ye chwo chwng
# 7.变量的删除 变量的子串 - ${var#string}
从变量左边开头,删除最短匹配word的子串
# 8.变量的删除 变量的子串 - ${var##string}
从变量左边开头,删除最长匹配word的子串
# 9.变量的删除 变量的子串 - ${var%string}
从变量右边开头,删除最短匹配word的子串
${filename%/*}
# 10.变量的删除 变量的子串 - ${var%%string}
从变量右边开头,删除最长匹配word的子串
${filename%%/*}
企业面试题
企业面试题 I am oldboy linux’s teacher driverzeng,welcome to our trainning. 请打印出这句话中,单词大于6的单 词并显示长度数。
#!/bin/bash
# File Name: __12_mianshiti.sh__
# Version: __v1.1__
# Author: __DriverZeng__
# Mail: __133411023@qq.com__
# Blog: __https://blog.driverzeng.com__
# DateTime: __2021-09-07 09:14__
text="I am oldboy linux's teacher driverzeng,welcome to our trainning."
for word in ${text//[,|.]/ };do
if [ ${#word} -gt 6 ];then
echo "单词:${word}"
echo "长度:${#word}"
echo "----------------"
fi
done
echo "I am oldboy linux's teacher driverzeng,welcome to our trainning."|awk -F '[ ,.]' '{for(i=1;i<=NF;i++) if(length($i) >6) print "单词:"$i,"长度:" length($i)}'
扩展变量
给变量设置默认值
写法 | 含义 |
---|---|
${parameter:-string} | 如果parameter没被赋值或其值为空,就以string作为默认值 |
${parameter:=string} | 如果parameter没被赋值或其值为空,就以string作为默认值,并将string赋值给parameter |
${parameter:?string} | 如果parameter没被赋值或其值为空,就以string作为错误输出,否则显示parameter内容 |
${parameter:+string} | 如果parameter没被赋值或其值为空,就什么都不做,否则用string替换变量内容 |
#1.变量默认值 ${variable:-string}
如果该变量没有被赋值,或者值为空,则使用string来代替他的默认值
[root@m01 scripts]# echo $name
[root@m01 scripts]# echo ${mode:-0644}
0644
[root@m01 scripts]# mode=0755
[root@m01 scripts]# echo ${mode:-0644}
0755
#2.变量默认值 ${variable:=string}
如果该变量没有被赋值,或者值为空,则使用string来代替他的默认值,并且将string的值赋值给变量
[root@m01 scripts]# echo $name
[root@m01 scripts]# echo ${name:=0755}
0755
[root@m01 scripts]# echo $name
0755
#3.变量默认值 ${variable:?string}
如果变量没有被赋值或者值为空,则输出一个报错信息,否则输出变量内容
[root@m01 scripts]# echo $owner
[root@m01 scripts]# echo ${owner:?command not found}
-bash: owner: command not found
[root@m01 scripts]# echo $?
1
[root@m01 scripts]# owner=root
[root@m01 scripts]# echo ${owner:?command not found}
root
#4.变量默认值 ${variable:+string}
如果变量没有被赋值或者值为空,则什么都不做,否则使用string替换变量内容
[root@m01 scripts]# echo $group
[root@m01 scripts]# echo ${group:+zls}
[root@m01 scripts]# group=www
[root@m01 scripts]# echo $group
www
[root@m01 scripts]# echo ${group:+zls}
zls
变量的赋值
- 直接复制:简单粗暴,例:name=zls
- 间接赋值:我们将一个命令执行的结果赋值给一个变量,例:IP=ifconfig eth0|awk ‘NR==2{print $2}’
- 交互赋值:我们需要跟脚本进行交互,例:read
- 传参复制:执行脚本的时候,将需要传递的变量值,写在脚本的后面 $1 $2 $3
交互赋值
read [option] variable
选项 变量名字
-p:提示信息
-s: 不显示输入内容
-a: 将所有的变量放入数组中
-t:设置超时时间(单位是秒)
[root@m01 scripts]# cat 13_read.sh
#!/bin/bash
# File Name: __13_read.sh__
# Version: __v1.1__
# Author: __DriverZeng__
# Mail: __133411023@qq.com__
# Blog: __https://blog.driverzeng.com__
# DateTime: __2021-09-07 10:03__
read -s -p "passwd: " pass
echo -e '\n'
read -s -p "new passwd: " new_pass
echo -e '\n'
if [ $pass == $new_pass ];then
echo 'successful'
else
echo '密码不一致'
fi
read -p "passwd: " pass1 pass2 pass3
echo $pass1
echo $pass2
echo $pass3
#!/bin/bash
# File Name: __13_read.sh__
# Version: __v1.1__
# Author: __DriverZeng__
# Mail: __133411023@qq.com__
# Blog: __https://blog.driverzeng.com__
# DateTime: __2021-09-07 10:03__
array=(zls cls wls tz)
echo ${array[@]}
echo ${array[2]}
read -p "passwd: " -a pass
echo ${pass[*]}
echo ${pass[0]}
echo ${pass[1]}
echo ${pass[2]}
echo ${pass[3]}
数据类型
-
字符串
- 使用引号引起来的收拾字符串,单引号
-
整型
- 只要是数字都是整型
-
数组
# 定义阶段
变量名=(str1 str2 str3)
# 调用
${变量名[*]} ## 取出全部
${变量名[下标]} ## 取单个
- 布尔
- true
- false
交互式脚本练习
写一个脚本,交互式输入主机名和IP,修改主机名和IP地址
please input a hostname: db01
please input a ip: 250
eth0和eth1 分别改成 10.0.0.250 172.16.1.250
简单版
思路分析
1.修改主机名
hostnamectl set-hostname 主机名
2.修改网卡
sed -i "###" 网卡配置文件
3.如何接收参数
交互:read
不交互:传参,位置变量
#!/bin/bash
# File Name: __simple_ip_host.sh__
# Version: __v1.1__
# Author: __DriverZeng__
# Mail: __133411023@qq.com__
# Blog: __https://blog.driverzeng.com__
# DateTime: __2021-09-07 11:38__
eth0_old_ip=$(ifconfig eth0|awk 'NR==2{print $2}')
eth1_old_ip=$(ifconfig eth1|awk 'NR==2{print $2}')
#1.接收用户传递的主机名
read -p 'pls input hostname: ' host_name
#2.修改主机名
hostnamectl set-hostname $host_name
#3.接收用户传递的eth0 ip地址
read -p 'pls input eth0 ip address: ' eth0_ip
#4.修改eth0网卡
sed -i "s#${eth0_old_ip}#${eth0_ip}#g" /etc/sysconfig/network-scripts/ifcfg-eth0
#5.接收用户传递的eth1 ip地址
read -p 'pls input eth1 ip address: ' eth1_ip
#6.修改eth1网卡
sed -i "s#${eth1_old_ip}#${eth1_ip}#g" /etc/sysconfig/network-scripts/ifcfg-eth1
#7.重启网卡
systemctl restart network
[root@sb01 scripts]# vim set_hostname_ipaddress.sh
#!/bin/bash
# File Name: __set_hostname_ipaddress.sh__
# Version: __v1.1__
# Author: __DriverZeng__
# Mail: __133411023@qq.com__
# Blog: __https://blog.driverzeng.com__
# DateTime: __2021-09-07 10:52__
old_ip=$(ifconfig|awk 'NR==2{print $2}')
network_conf=/etc/sysconfig/network-scripts/ifcfg-eth
read -p 'please input a hostname: ' host_name
read -p 'please input a ip host bit: ' host_bit
# 1.修改主机名
hostnamectl set-hostname ${host_name}
# 2.修改IP地址
sed -i "s#${old_ip}#${old_ip/${old_ip##*.}/${host_bit}}#g" ${network_conf}0
sed -i "s#${old_ip:+172.16.1.${old_ip##*.}}#${old_ip:+172.16.1.${host_bit}}#g"
${network_conf}1
# 3.重启网卡
systemctl restart network