Shell脚本变量

Shell脚本变量

1.Shell变量概述

1.什么是变量

变量是Shell传递数据的一种方法,简单理解:就是一个固定的字符串区表示不固定的值,便于后续引用。

2.变量命令规范

变量定义时名称有要求:字母、数字、下划线组成,尽量字母开头,{变量名最好具备一定的含义}

ip=10.0.0.100

ip1=10.0.0.100

Hostname_Ip=10.0.0.100

hostname_IP=10.0.0.100

等号是赋值,需要注意:等号两边不能有空格,其次定义的变量不要与系统命令出现冲突。

1.变量的定义,需要具备一定的含义,同时不要与系统的命令产生冲突。
	HostName_IP
	HostName_Network
	
2.定义变量示例
	[root@zxm ~]# HostName=$(hostname)
	[root@zxm ~]# echo $HostName
	zxm
	
3.错误定义变量方式
	[root@zxm ~]# HostName = $(hostname)   //不能有空格

自定义变量练习	
[root@zxm ~]# var="hello shell"
[root@zxm ~]# echo $var
hello shell
[root@zxm ~]# echo $var_log		#$var_log当做一个整体
[root@zxm ~]# echo ${var}_log	
hello shell_log

3.shell变量定义的方式

  1. 用户自定义变量:人为定义变量名称;
  2. 系统环境变量:保存的是和系统操作环境相关的数据;
  3. 位置参数变量:向脚本中进行参数传递,变量名不能自定义,变量作用是固定的。
  4. 预定义的变量:是Bash中已经定义好的变量,变量名不能自定义,变量作用也是固定的。

4.shell变量定义实践

1.用户自定义变量示例,当前shell有效
#1)定义变量,变量名=变量值。不能出现“-”命名
[root@backup ~]# var="hello zxm"   #定义变量有空格必须使用双引号

#2)引用变量,$变量名或者${变量名}
[root@backup ~]# echo $var
hello zxm
[root@backup ~]# echo ${var}
hello zxm
[root@backup ~]# echo ${var}_log
hello_zxm_log

#3)查看变量,set显示所有变量,包括自定义变量和环境变量
[root@backup ~]# set |grep var
var=hello_zxm

#4)取消变量,作用范围:仅在当前shell中有效
[root@backup ~]# unset var

#5)注意事项,引用变量时注意 “”  双引号属于弱引用, ''单号输入强引用
[root@backup ~]# var=zxm
[root@backup ~]# echo $var
zxm
[root@backup ~]# echo "$var is good person"
zxm is good person
[root@backup ~]# echo '$var is good person'
$var is good person

		
1.在定义变量的时候,比如: var="$(hostname)"	
2.在引用变量的时候,尽可能的使用双引号     echo "$var"
3.在我们使用echo输出的时候,如果输出的字符串中有特殊的符号,建议使用单引号  echo '#$123'

[root@zxm ~]# echo "$var is good is \$500"
	希望$var被解析
	而$500 不被解析


2.系统环境变量示例,在当前shell和子shell有效
#1)定义环境变量:export  变量,将自定义变量转换成环境变量
[root@zxm shell]# var2=hello
[root@zxm shell]# echo $var2
hello
[root@zxm shell]# cat a.sh
#!/bin/bash
echo $var2
[root@zxm shell]# sh a.sh   #执行a.sh 时,会使用另一个bash去执行,就访问不到$VAR1的值

[root@zxm shell]# export var2=hello #将变量转为环境变量
[root@zxm shell]# sh a.sh   #再次执行脚本
hello
#2)使用系统已定义好的环境变量
[root@backup shell]# cat env.sh 
#!/bin/bash
echo "用户的家目录: $HOME"
echo "当前主机名是: $HOSTNAME"
echo "当前所在目录: $PWD"

[root@backup shell]# sh env.sh
用户的家目录: /root
当前主机名是: backup
当前所在目录: /scripts/shell
3.预先定义的变量参数示例,系统内置变量的使用方法。
#1.脚本如下
[root@zxm shell]# cat variable.sh
#!/bin/bash
echo "#当前shell脚本的文件名: $0"
echo "#第1个shell脚本位置参数:$1"
echo "#第2个shell脚本位置参数:$2"
echo "#第3个shell脚本位置参数:$3"
echo "#所有传递的位置参数是: $*"
echo "#所有传递的位置参数是: $@"
echo "#总共传递的参数个数是: $#"
echo "#当前程序运行的 PID 是: $$"
echo "#上一个命令执行的返回结果: $?"

#2.执行结果如下
[root@backup shell]# sh variable.sh  11 22 33 44 55 66
#当前shell脚本的文件名: variable.sh
#第1个shell脚本位置参数:11
#第2个shell脚本位置参数:22
#第3个shell脚本位置参数:33
#所有传递的位置参数是: 11 22 33 44 55 66
#所有传递的位置参数是: 11 22 33 44 55 66
#总共传递的参数个数是: 6
#当前程序运行的 PID 是: 49194
#上一个命令执行的返回结果: 0


需要注意的是: shell $*$@的区别

[root@zxm shell]# cat tt.sh
#! /bin/bash
test() {
        echo "未加引号,二者相同"
        echo $*
        echo $@
        echo "加入引号后对比"
	echo "----"\$*----""
        for N in "$*"
        do
           echo $N
        done

	echo "----"\$@----""
        for N in "$@"
        do
           echo $N
        done
}
test  11 22 33

执行后结果如下

[root@zxm shell]# sh tt.sh
未加引号,二者相同
11 22 33
11 22 33
加入引号后对比
----$*----
11 22 33
----$@----
11
22
33

可以看到不加引号时,二者都是返回传入的参数,但加了引号后,此时\(\*把参数作为一个字符串整体(单字符串)返回,\)@把每个参数作为一个字符串返回

4.补充:将命令执行的结果传递给变量(命令替换)
#根据系统时间,打印几年时间和明年时间
[root@zxm shell]# echo "This is $(date +%Y) year"
This is 2019 year
[root@zxm shell]# echo "This is $(($(date +%Y)+1)) year"
This is 2020 year

#命令的嵌套使用,使用$( $( ) )

[root@backup shell]# find /root/ -name *.txt
[root@backup shell]# db=$(tar czvf root.tar.gz  $(find /root/ -name *.txt))
[root@backup shell]# echo $db

2.Shell变量赋值

除了自定义变量,以及系统内置变量,还可以使用read命令通过交互方式传递变量

1.read示例语法

[root@backup scripts]# cat read1.sh 
#!/bin/bash
read -p "请输入你要备份的目录:" varsfile

echo "你要备份的目录是:" $varsfile

执行效果:

[root@backup scripts]# sh read1.sh 
请输入你要备份的目录:/etc           //ctrl+u 可以清掉输出错误的信息
你要备份的目录是: /etc

2.read示例语法,简单备份场景

[root@backup scripts]# cat read2.sh
#!/bin/bash
back_dir1=/var/backup
read -p "请输入您的备份目录:" back_dir2
echo $back_dir1
echo $back_dir2

执行效果:

[root@backup scripts]# sh read2.sh 
请输入您的备份目录:/etc
/var/backup
/etc

3.read示例语法,测试用户输入的IP是否通

  1. 执行脚本时,提示:请输入ip;
  2. 使用ping命令去探测是否是通,如果是通的则返回GG,不同则返回NG;
if 语法

if [];then
	else
fi 
[root@backup scripts]# cat read3.sh 
#!/bin/bash 
#1.提示用户输入一个IP地址
read -p "请输入您的ip:" ip
echo "您输入的ip是:" $ip
#2.使用ping命令检测IP地址是否通讯
ping  -W1 -c3  $ip  &>/dev/null
rc=$?   //将$?的0或非0的值赋给了rc,防止ping命令之后其他操作导致$?的值发生改变

if [ $rc == 0 ] ; then

	echo "$ip 能正常通信。"
 
else

	echo "$ip 不能正常通信。"

fi

4.使用read命令写一个脚本修改主机名和IP地址

  1. 提示用户输入主机名称;
  2. 提示用户输入IP地址;
  3. 询问用户是否确认此操作;
  4. 执行;
[root@backup scripts]# cat read4.sh
#!/bin/bash

read -p "请输入主机名称:"  HostName
read -p "请输入主机ip:"  IP 
read -p "Are you sure!(yes/no):"  var1

if [ $var1 == "yes" ];then

#修改主机名
hostnamectl set-hostname $HostName

#获取本机ip
IP1=$(ifconfig eth1 | awk  'NR==2{print $2}')

#修改IP地址
sed -i  "s/IPADDR=$IP1/IPADDR=$IP/"  /etc/sysconfig/network-scripts/ifcfg-eth1

#重启网卡
systemctl restart network

else

	 exit
fi  

3.Shell变量替换

变量 说明
$ 从头开始匹配,最短删除
$ 从头开始匹配,最长删除
$ 从尾开始匹配,最短删除
$ 从尾开始匹配,最长删除
$ 替换变量内的旧字符串为新字符串,只替换第一个
$ 替换变量内的旧字符串为新字符串,全部替换

1.从前往后删除变量内容

[root@backup ~]# qq=123456789
[root@backup ~]# echo ${qq}          //输出变量的值
123456789
[root@backup ~]# echo ${qq#*3}       //从头开始匹配,删除最短,保留最长的
456789
[root@backup ~]# echo ${qq##*7}       //从头开始匹配,删除最长,保留最短的
89

2.从后往前删除变量内容

[root@backup ~]# echo ${qq}          //输出变量的值
123456789
[root@backup ~]# echo ${qq%7*}       
123456
[root@backup ~]# echo ${qq%3*}
12

3.变量内容替换

[root@backup ~]# qq=11223344
[root@backup ~]# echo ${qq}
11223344
[root@backup ~]# echo ${qq/3/4}
11224344
[root@backup ~]# echo ${qq//3/4}
11224444

【shell练习题-1】

1.查看内存/当前使用状态,如果使用率超过80%则报警发邮件

查看内存:free -m
[root@backup ~]# free -m 
              total        used        free      shared  buff/cache   available
Mem:           3770         242        3069          43         458        3267
Swap:          2047           0        2047

使用awk过滤Mem行
[root@backup ~]# free -m |awk '/^Mem/'
Mem:           3770         242        3069          43         458        3268

查看内存百分比: 使用的/总的*100%= 
[root@backup ~]# free -m |awk '/^Mem/ {print $3/$2*100}'
6.4191

[root@backup scripts]# cat free_use.sh
#!/bin/bash

free_use=$(free -m |awk '/^Mem/ {print $3/$2*100}')

echo ${free_use%.*}%

if [ ${free_use%.*} -gt 80 ];then
         mail  -s "内存超过了80%"  xxxx@qq.com
else
        exit
fi

2.场景实践,在/backup下创建10个.txt的文件,找到/backup目录下所有后缀名为.txt的文件
1)批量修改txt为txt.bak
2)把所有的.bak文件打包压缩为123.tar.gz
3)批量还原文件的名字,及把增加的.bak再删除

[root@backup ~]# mkdir /backup
[root@backup ~]# mkdir /backup/{1..10}.txt
[root@backup ~]# find /backup/ -name "*.txt"

[root@backup ~]# cat rename.sh 
#!/bin/bash

#将txt批量修改为txt.bak

find /backup/ -name "*.txt" |sed -r 's#(.*)#mv \1 \1.bak#g' |bash

#打包

tar czf  /backup/123.tar.gz $(find /backup/ -iname "*.bak")

#还原名字

find /backup/ -name "*.bak"|sed -r 's#(.*).bak#mv \1.bak \1#g' |bash

[root@backup ~]# tar tf /backup/123.tar.gz 
backup/1.txt.bak
backup/2.txt.bak
backup/3.txt.bak
backup/4.txt.bak
backup/5.txt.bak
backup/6.txt.bak
backup/7.txt.bak
backup/8.txt.bak
backup/9.txt.bak
backup/10.txt.bak

#变量替换方式   

#!/usr/bin/bash
File_txt=$(find /backup/ -type f -iname "*.txt"|xargs >/backup/txt.tt)
for i in $(cat /backup/txt.tt)
do
    mv  $i $i.bak
done

tar czf /backup/123.tar.gz ./*.bak

File_bak=$(find /backup/ -type f -iname "*.bak" >/backup/tar.tt)
for j in $(cat /backup/tar.tt)
do
   mv $j ${j%.*}
done
#rename命令
#!/bin/bash
#定义变量
T=txt
B=bak

#把backup目录下.txt结尾的文件修改成txt.bak
cd /backup && rename $T $T\.$B *.txt

#把所有的.bak结尾的文件打包压缩为123.tar.gz
tar zcvf /backup/123.tar.gz /backup/*.bak

#还原文件的名字
rename $T\.$B $T *

【shell练习题-2】

1.用shell或者python编写一个脚本,要求如下:

​ 在每个月第一天备份并压缩/etc目录下的所有内容,存放在/root/bak目录里面,且文件名为如下形式yymmdd_etc,yy为年,mm为月,dd为日。脚本名称为fileback存放在root的家目录下。

[root@backup ~]# cat fireback 
#!/bin/bash

#声明变量
Dest=/root/bak
Date=$(date +%Y%m%d)

#判断存放目录是否存在
[ ! -d $Dest ] && mkdir -p $Dest

#备份
tar czf $Dest/${Date}_etc.tar.gz /etc

[root@backup ~]# crontab -e
00 23 1 * *  bash /root/fireback

4.Shell变量运算

1.整数运算,expr $(()) %[],不支持小数运算

操作符 含义
num1 + num2 求和
num1 - num2 求差
num1 * num2 求积
num1 / num2 求商
num1 % num2 求余
#定义变量,使用expr、$(())、%[]进行加减乘除。expr必须空格隔开。

[root@backup ~]# num1=5
[root@backup ~]# num2=2
----------------------------------------------------expr---------------------------------------------------------------
[root@backup ~]# expr num1 + num2 
[root@backup ~]# expr $num1 + $num2 
7
[root@backup ~]# expr $num1 - $num2 
3
[root@backup ~]# expr $num1 / $num2 
2
[root@backup ~]# expr $num1 % $num2 
1
[root@backup ~]# expr $num1 \* $num2 
10
---------------------------------------------------$(())---------------------------------------------------------------
[root@backup ~]# echo $(($num1 + $num2))
7
[root@backup ~]# echo $(($num1 - $num2))
3
[root@backup ~]# echo $(($num1 / $num2))
2
[root@backup ~]# echo $(($num1 % $num2))
1
[root@backup ~]# echo $(($num1 * $num2))
10
---------------------------------------------------%[]-----------------------------------------------------------------
[root@backup ~]# echo $[$num1+$num2]
7
[root@backup ~]# echo $[$num1-$num2]
3
[root@backup ~]# echo $[$num1/$num2]
2
[root@backup ~]# echo $[$num1*$num2]
10
[root@backup ~]# echo $[$num1%$num2]
1

2.小数运算bc,用的不是很多,了解即可

[root@backup ~]# yum install bc -y
[root@backup ~]# echo '2*4' |bc 
8
[root@backup ~]# echo "2^4" |bc
16
[root@backup ~]# echo "scale=2;6/4" |bc    #取2位小数
1.50
[root@backup ~]# awk 'BEGIN{print 1/2}'
0.5

5.Shell变量案例

1.使用Shell脚本打印,系统版本、内核版本平台、虚拟平台、静态主机名、eth0网卡IP地址、lo网卡IP地址
当前主机的外网IP地址curl icanhazip.com

[root@backup scripts]# cat 5.sh 
#!/bin/bash

#系统版本
System=$(hostnamectl |awk 'NR==7{print $3,$4,$5,$6}')

#内核版本平台
Kernel=$(hostnamectl |awk 'NR==9{print $3}')

#虚拟平台
Virtualization=$(hostnamectl |grep Virtualization |awk '{print $2}')

#静态主机名
Statichostname=$(hostnamectl |awk 'NR==1{print $3}')

#eth0网卡的IP地址
Eth0=$(ifconfig eth0|awk 'NR==2 {print $2}')

#LO网卡的IP地址
Lo=$(ifconfig lo|awk 'NR==2 {print $2}')

#当前主机的外网ip地址
Network_T=$(curl -s icanhazip.com)

echo "系统版本是:" $System
echo "内核版本平台:" $Kernel
echo "虚拟平台:" $Virtualization
echo "静态主机名:" $Statichostname
echo "eth0网卡的IP地址:" $Eth0
echo "LO网卡的IP地址:" $Lo
echo "当前主机的外网ip地址:" $Network_T


[root@backup scripts]# sh 5.sh 
系统版本是: CentOS Linux 7 (Core)
内核版本平台: 3.10.0-1160.11.1.el7.x86_64
虚拟平台: vmware
静态主机名: backup
eth0网卡的IP地址: 10.0.0.41
LO网卡的IP地址: 127.0.0.1
当前主机的外网ip地址: 120.204.78.23

2.需求描述:变量string="Bigdata process is Hadoop, Hadoop is open source project",执行脚本后,打印输出string字符串变量,并给出用户以下选项:
1)、打印string长度
2)、删除字符串中所有的Hadoop
3)、替换第一个Hadoop为Linux
4)、替换全部Hadoop为Linux
用户输入数字1|2|3|4,可以执行对应项的功能,输入q|Q则退出交互模式

[root@backup scripts]# cat 6.sh 
#!/bin/bash

string="Bigdata process is Hadoop, Hadoop is open source project"

echo $string

echo "-------------------------------------------"
echo "-------------------选项--------------------"
echo "-----------1.打印string长度----------------"
echo "-----------2.删除字符串中所有的Hadoop------"
echo "-----------3.替换第一个Hadoop为Linux-------"
echo "-----------4.替换全部Hadoop为Linux---------"
echo "-------------------------------------------"

read -p "输入数字1|2|3|4,可以执行对应项的功能,输入q|Q则退出交互模式:" var
if [ $var -eq 1 ];then
	#echo 当前string变量的长度是: ${#string}
	echo 当前string变量的长度是: echo ${string}|wc -L	
fi

if [ $var -eq 2 ];then
	echo ${string//Hadoop/}
fi

if [ $var -eq 3 ];then
	echo ${string/Hadoop/Linux}
fi

if [ $var -eq 4 ];then
	echo ${string//Hadoop/Linux}
fi

if [ $var == q ];then
	exit
fi

if [ $var == Q ];then
	exit
fi

posted @ 2021-02-22 17:45  水煮沉浮~大刀肉  阅读(373)  评论(0)    收藏  举报