shell脚本之read和变量运算
文章目录
0.执行方式和加不加bash区别
执行方式分为两种:
1.加执行权限 ./script_filename.sh
2.通过bash直接翻译 bash script_filename.sh
#!/usr/bin/bash 加与不加区别在哪?
1.如果你明确清楚这是一个什么类型的脚本,直接调用对应的解释器执行,没有影响?
2.如果你不清楚是什么类型的脚本, 直接使用./执行,那么会读取该脚本的第一行
如果第一行是#!/usr/bin/bash 或者 没有写该行,那么都将使用默认的bash翻译
问题: 如果我是一个python脚本,没有写开头,那么执行一定会报错
因为默认查找的是bash解释器,而我的文件需要用python解释器来翻译.
添加命令解释器的几种方式:
#!/usr/bin/bash
#!/usr/bin/sh
#!/usr/bin/env bash
#!/usr/bin/env python
#1.示例1
[root@manage ]# cat init.sh
#/usr/bin/bash
echo "123"
[root@manage ]# sh +x init.sh
123
#2.示例2
cat init.sh
#!/usr/bin/env python
print "(hehe)"
[root@manage ]# ./init.sh
(hehe)
1.打开新的脚本自动添加注释信息
[root@manage ~]# cat .vimrc
autocmd BufNewFile *.sh exec ":call AddTitleForShell()"
function AddTitleForShell()
call append(0,"#!/bin/bash")
call append(1,"# **********************************************************")
call append(2,"# * Author : qqq")
call append(3,"# * Email : xxxxx@163.com")
call append(4,"# * Create time : ".strftime("%Y-%m-%d %H:%M"))
call append(5,"# * Filename : ".expand("%:t"))
call append(6,"# * Description : ")
call append(7,"# **********************************************************")
endfunction
[root@manage ~]# vim init.sh
#!/bin/bash
# **********************************************************
# * Author : qqq
# * Email : xxxxx@163.com
# * Create time : 2022-04-16 09:54
# * Filename : init.sh
# * Description :
# **********************************************************
1.1 脚本变量符号的概念
#1.单引号和双引号区别
单引号:强引用,即所见即所得:[root@manage ~]# echo '$100'
双引号:弱引用,[root@manage ~]# echo "\$100"
#2.设置全局变量:export变量,将自定义变量转换成环境变量
[root@manage ~]# export Abc=test
[root@manage ~]# echo $Abc
test
[root@manage ~]# vim test.sh
#!/bin/bash
echo $Abc
[root@manage ~]# sh +x test.sh
#3.预先定义的变量参数示例,系统内置变量的使用方法,需要注意$*和$@的区别
#示例
[root@manage ~]# 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 "#上一个命令执行的返回结果是:$?"
#执行结果
[root@manage ~]# sh variable.sh 11 22 33 44
#当前shell脚本的文件名:variable.sh
#第1个shell脚本的位置参数:11
#第2个shell脚本的位置参数:22
#第3个shell脚本的位置参数:33
#所有传递的位置参数是:11 22 33 44
#所有传递的位数参数是:11 22 33 44
#总共传递的参数个数是:4
#当前程序运行的 PID 是:7594
#上一个命令执行的返回结果是:0
#4.$*和$@的区别
不加引号:两者相同
加入引号:$*将参数作为一个字符串整体(单字符串)返回,$@将参数作为一个字符串返回
#需求1:通过位置传参方式, 创建 Linux 系统账户及密码,执行 useradd.sh username password
[root@manage day01]# cat useradd.sh
#!/bin/bash
#判断:如果传递的参数不是2个,输出一句话,并且退出
if [ $# -ne 2 ];then
echo "USAGE: $0 请传递2个参数:[username | password]"
exit
fi
useradd $1
echo "$2" |passwd --stdin $1
[root@manage day01]# sh +x useradd.sh 111 222 333
USAGE: useradd.sh 请传递2个参数:[username | password]
[root@manage day01]# sh +x useradd.sh tttt 123456
Changing password for user tttt.
passwd: all authentication tokens updated successfully.
1.2 read的用法
read选项 | 选项含义 |
---|---|
-p | 打印信息 |
-t | 限定时间 |
-s | 不回显 |
-n | 指定字符个数 |
#1.示例1(echo -n是不让换行,打印在一行)
[root@manage day01]# cat var01.sh
#!/bin/bash
echo -n "Login: "
read acc
echo -n "Password: "
read pw
echo "你输入的用户名是:$acc 你输入的密码是:$pw
[root@manage day01]# sh var01.sh
Login: root
Password: 111
你输入的用户名是:root 你输入的密码是:111
#2.升级一下,用read -p方式
[root@manage day01]# cat var02.sh
#!/bin/bash
read -p "Login: " user
read -p "password: " pw
echo "你输入的用户名是:$user 你输入的密码是:$pw"
[root@manage day01]# sh var02.sh
Login: root
password: 111
你输入的用户名是:root 你输入的密码是:111
#3.加-t参数,如果5秒内不输入密码,则自动退出
[root@manage day01]# cat var02.sh
#!/bin/bash
read -p "Login: " user
read -t5 -p "password: " pw
echo "你输入的用户名是:$user 你输入的密码是:$pw"
[root@manage day01]# sh var02.sh
请输入用户名 Login: root
请输入密码:password: 你输入的用户名是:root 你输入的密码是:
#4.加-n参数,现在密码的长度
[root@manage day01]# cat var02.sh
#!/bin/bash
read -p "Login: " user
read -t5 -n8 -p "password: " pw
echo "你输入的用户名是:$user 你输入的密码是:$pw"
[root@manage day01]# sh +x var02.sh
请输入用户名 Login: root
请输入密码:password: 12345678你输入的用户名是:root 你输入的密码是:12345678
[root@manage day01]# 9
#5.加-s参数,密码应该不让显示出来
[root@manage day01]# cat var02.sh
#!/bin/bash
read -p "Login: " user
read -t5 -n8 -s -p "password: " pw
echo "你输入的用户名是:$user 你输入的密码是:$pw"
[root@manage day01]# sh +x var02.sh
请输入用户名 Login: root
请输入密码:password: 你输入的用户名是:root 你输入的密码是:12345678
#示例1:模拟Linux登录界面
[root@manage day01]# cat var03.sh
#!/bin/bash
echo "$(hostnamectl |awk -F ':' '/Operating System/{print $2}')"
echo "Kernel $(uname -r) on an $(uname -m)"
read -p "$(hostname) login: " user
read -s -t5 -n8 -p "Passwd:" pw
echo ""
echo "你输入的用户名是: $user 你输入的密码是: $pw"
[root@manage day01]# sh +x var03.sh
CentOS Linux 7 (Core)
Kernel 3.10.0-957.el7.x86_64 on an x86_64
manager login: root
Passwd:
你输入的用户名是: root 你输入的密码是: 123
#示例2:使用 read编写一个备份脚本,需要用户传递2个参数,源和目标
[root@manage day01]# cat var04.sh
#!/bin/bash
echo "请按照下面提示输入你要备份的源和目标位置"
read -p "请输入你要备份的源文件或目录:" Src
read -p "请输入你要备份的目标位置: " Desc
echo -e "\t你要备份的源是: $Src
你要备份的目标是: $Desc"
read -p "是否确认备份[ y|n ]" Action
if [ $Action == y ];then
cp -rpv $Src $Desc
fi
[root@manage day01]# sh +x var04.sh
请按照下面提示输入你要备份的源和目标位置
请输入你要备份的源文件或目录:/etc/passwd
请输入你要备份的目标位置: /opt/
你要备份的源是: /etc/passwd
你要备份的目标是: /opt/
是否确认备份[ y|n ]y
‘/etc/passwd’ -> ‘/opt/passwd’
#示例3:使用read编写一个探测主机存活脚本,需要用户传递测试的IP地址
[root@manage day01]# sh +x var05.sh
请输入需要探测主机的ip: 10.0.0.100
10.0.0.100主机不存活
[root@manage day01]# cat var05.sh
#!/bin/bash
read -p "请输入需要探测主机的ip: " ip
ping -W1 -c1 $ip >/dev/null
if [ $? -eq 0 ];then
echo "$ip主机存活"
else
echo "$ip主机不存活"
fi
[root@manage day01]# sh +x var05.sh
请输入需要探测主机的ip: 10.0.0.201
10.0.0.201主机存活
[root@manage day01]# sh +x var05.sh
请输入需要探测主机的ip: 10.0.0.100
10.0.0.100主机不存活
#示例4.使用read编写一个修改系统主机名称脚本
[root@manage day01]# cat var06.sh
#!/bin/bash
Hostname=$(hostname)
echo "当前主机名:${Hostname}"
read -p "请输入新的主机名称:" newhostname
read -p "你确定要将${Hostname}修改为${newhostname}吗" Action
if [ $Action == y ];then
hostnamectl set-hostname $newhostname
bash
else
exit
fi
[root@manage day01]# sh +x var06.sh
当前主机名:manage
请输入新的主机名称:111
你确定要将manage修改为111吗:[ y|n ]y
1.3 shell变量替换
变量替换的几种方式
变量 | 说明 |
---|---|
${变量#匹配规则} | 从头开始匹配,最短删除 |
${变量##匹配规则} | 从头开始匹配,最长删除 |
${变量%匹配规则} | 从尾开始匹配,最短删除 |
${变量%%匹配规则} | 从尾开始匹配,最长删除 |
${变量/旧字符串/新字符串} | 替换变量内的旧字符串为新字符串,只替换第一个 |
${变量//旧字符串/新字符串} | 替换变量内的旧字符串为新字符串,全部替换 |
#示例1:从前往后删除变量内容
-------------#----------------------
[root@manage day01]# url=www.sina.com.cn
[root@manage day01]# echo $url
www.sina.com.cn
[root@manage day01]# echo ${url#*.} #单个#是从头开始匹配,最短删除
sina.com.cn
[root@manage day01]# echo ${url##*.} #2个#是从头开始匹配,最长删除
cn
#示例2:从后往前删除变量内容
--------------%------------------
[root@manage day01]# echo ${url}
www.sina.com.cn
[root@manage day01]# echo ${url%.*}
www.sina.com
[root@manage day01]# echo ${url%.*.*}
www.sina
[root@manage day01]# echo ${url%.*.*.*}
www
#示例3:替换变量中的内容
-------------/------------------
[root@manage day01]# echo ${url}
www.sina.com.cn
[root@manage day01]# echo ${url/sina/baidu}
www.baidu.com.cn
[root@manage day01]# echo ${url//c/C}
www.sina.Com.Cn
#需求1.删除qqq包括后面的内容
[root@manage day01]# tt="I am ttt qqq aaa"
[root@manage day01]# echo $tt
I am ttt qqq aaa
[root@manage day01]# echo ${tt%qqq*}
I am ttt
#需求2.如何替换 $PATH 中的/bin/替换为/BIN/
[root@manage day01]# echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin
[root@manage day01]# echo ${PATH//bin/BIN}
/usr/local/sBIN:/usr/local/BIN:/usr/sBIN:/usr/BIN:/root/BIN
#需求3:变量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,可以执行对应项的功能
[root@manage day01]# cat var07.sh
#!/bin/bash
string="Bigdata process is Hadoop, Hadoop is open source project"
echo ${string}
echo "1、打印string长度"
echo "2、删除字符串中所有的Hadoop"
echo "3、替换第一个Hadoop为Linux"
echo "4、替换全部Hadoop为Linux"
read -p "请输入数字:1|2|3|4| 执行对应项的功能:" Action
if [ $Action -eq 1 ];then
echo ${#string}
fi
if [ $Action -eq 2 ];then
echo ${string//Hadoop/}
fi
if [ $Action -eq 3 ];then
echo ${string/Hadoop/Linux}
fi
if [ $Action -eq 4 ];then
echo ${string//Hadoop/Linux}
fi
#需求4:查看内存/当前使用状态,如果使用率超过80%则报警发邮件,思路如下:
1.当前内存使用百分比是多少
2.进行判断比对
如果大于80% 则触发邮件
否则,over
已使用的内存 / 总内存 * 100 = 使用的百分比
[root@manage day01]# cat var08.sh
#!/bin/bash
Mem_use=$(free -m |awk '/Mem/ {print $3/$2*100}')
if [ ${Mem_use%.*} -ge 10 ];then
echo "你的内存使用率大于80%,当前使用率为${Mem_use}%"
fi
[root@manage day01]# sh +x var08.sh
你的内存使用率大于80%,当前使用率为88.8384%
1.4 shell变量运算
变量运算使用什么方式来实现?
通常整数运算有**expr、 ( ( ) ) 、 (())、 (())、[]**等方式,小数运算有bc、awk等
操作符 | 含义 |
---|---|
num1 + num2 | 加 |
num1 - num2 | 减 |
num1 * num2 | 乘 |
num1 / num2 | 除 |
num1 % num2 | 余 |
#基本用法
[root@manage day01]# num1=5
[root@manage day01]# num2=10
[root@manage day01]# echo $(( $num1 + $num2))
15
[root@manage day01]# echo $[ $num1 + $num2 ]
15
[root@manage day01]# expr $num1 + $num2
15
#需求1:根据系统时间,打印今年和明年时间
[root@manage day01]# cat var09.sh
#!/bin/bash
echo "今年的时间是:$(date +%Y)"
echo "明年的时间是:$(( $(date +%Y) +1 ))"
[root@manage day01]# sh +x var09.sh
今年的时间是:2022
明年的时间是:2023
#需求2:根据系统时间获取今年还剩下多少星期,已经过了多少星期。思路如下:
date +%j 已经过了多少天
一年有365天 已经过了 106 = 还剩下 365-106 = 259 / 7 = 还剩下多少周
已经过了 106 天 / 7 = 已经过了多少周
[root@manage day01]# cat var10.sh
#!/bin/bash
Date=$(date +%j)
echo "今年已经过去了${Date}天"
echo "今年还剩$[ 365-${Date} ]天"
echo "今年过去了$[ ${Date}/7 ]星期"
echo "今年还剩$[ (365-${Date})/7 ]星期"
[root@manage day01]# sh +x var10.sh
今年已经过去了106天
今年还剩259天
今年过去了15星期
今年还剩37星期
#需求3:完成一个计算器功能: 传入2个值,然后对传入的值进行 加 减 乘 除,思路如下:
1.使用read让用户传值: $1 $2
2.对传入的值进行运算:
3.输出对应的结果.
[root@manage day01]# cat var11.sh
#!/bin/bash
echo "$1 + $2 = $[ $1 + $2 ]"
echo "$1 - $2 = $[ $1 - $2 ]"
echo "$1 / $2 = $[ $1 / $2 ]"
echo "$1 * $2 = $[ $1 * $2 ]"
echo "$1 % $2 = $[ $1 % $2 ]"
[root@manage day01]# cat var11.sh
#!/bin/bash
read -p "请输入第一个值:" a
read -p "请输入第二个值:" 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 ]"
[root@manage day01]# sh +x var11.sh
请输入第一个值:1
请输入第二个值:2
1 + 2 = 3
1 - 2 = -1
1 / 2 = 0
1 * 2 = 2
1 % 2 = 1