shell脚本实操学习之变量、数组

shell脚本实操学习之变量、数组

  • shell脚本
  • shell介绍
    • shell介绍
    • shell功能
  • shell脚本语法
    • 如何抒写shell脚本
    • shell脚本运行方法
    • shell中的符号
    • 管道
    • 重定向
      • 磁盘分区脚本案例
    • shell脚本中的数学运算
    • 脚本退出
  • 格式化输出
    • echo语法
    • 颜色字体
  • 格式化输入
    • read命令
  • shell变量
    • 变量介绍
    • 变量分类
    • 变量管理
      • 定义变量
      • 读取变量内容
      • 取消变量unset
  • shell数组
    • 数组介绍
    • 基本数组
      • 数组的语法
      • 数组读出
      • 数组赋值
      • 查看数组
      • 访问数组元素
      • 遍历数组
    • 关联数组
      • 定义关联数组
      • 关联数组赋值
      • 访问数组元素
      • 遍历数组
    • 案例分享

shell脚本

日常运维工作大部分是一些繁琐的重复的工作,每天80%的工作就是重复干昨天的事情,而且工作量还比较大, 那么摆在运维面前的选择是:
A:自己手动搞定一切
B:让机器搞定一切


shell的学习阶段:
1)能看懂shell脚本
2)能改shell脚本
3)能自己写shell脚本
4)能优化shell脚本

shell介绍

shell介绍

shell是一个程序,采用C语言编写,是用户和linux内核沟通的桥梁。它既是一种命令语言,也是一种解释器的编程语言。通过一个图表来看下shell的作用。
shell脚本实操学习之变量、数组_第1张图片
拓展知识:

  • kernel:为软件服务,接收用户或软件指令驱动硬件,完成工作。
  • shell:命令解释器。
  • user:用户接口,对接用户。

shell功能

  • 命令行解释功能
  • 启动程序
  • 输入输出重定向
  • 管道连接
  • 文件名置换(echo /*)
  • 变量维护
  • 环境控制
  • shell编程

shell脚本语法

shell脚本就是将完成一个任务的所有的命令按照执行的先后顺序,自上而下写入到一个文本文件中,然后给予执行权限。

如何抒写shell脚本

shell脚本的命名:

名字要有意义;
文件要有扩展名,建议使用.sh结尾;
名字不要太长,建议30字节以内解决。

shell脚本格式:

shell脚本开头必须制定脚本运行环境以#!这个特殊符号组合来组成。如:#!/bin/bash指定该脚本是运行解析由/bin/bash来完成的:
shell中的注释使用#


shell脚本中,最好加入脚本说明字段:
#1)定义脚本的执行环境
#!/usr/bin/bash
#2)脚本信息
#Author:bai
#Created Time:xxxx-xx-xx xx:xx
#Release:1.0
#Script Description : nginx intstall script
#4)脚本组成
#解释环境 #!/usr/bin/bash | python | perl
#注释说明
#执行代码

shell脚本运行方法

#5)运行脚本
#1. 给执行权限
#2. 解释器直接运行,不需要给权限

Python
vim hello.py
#!/usr/bin/env python
print ("hello world!");

shell中的符号

注意:不要和正则表达式混淆。

~: 家目录 # cd ~ 代表进入用户家目录
!:执行历史变量 !! 执行上一条命令
$:变量中取内容符
+ - * % :对应数学运算:加、减、乘、除、取余数
&:后台执行
*:星号是shell中的通配符,匹配所有
?:问号是shell中的通配符,匹配除回车以外的一个字符
;:分号可以在shell中一行执行多个命令,命令之间用分号分割
|:管道符,上一个命令的输出作为下一个命令的输入 cat filename | grep “abc”
\:转义字符
``:反引号,命令中执行命令。echo “today is `date +%F`”
’ ':单引号,脚本中字符串要用单引号引起来,但是不同于双引号的是,单引号不解释变量。
" ":双引号,脚本中出现的字符串可以用双引号引起来

管道

| :管道符在shell中使用是最多的,很多组合命令都要通过组合命令来完成输出,管道符其实就是下一个命令对上一个命令的输出做处理。

重定向

>:重定向输入 ,覆盖原数据
>>:重定向追加输入,在原数据的末尾添加
<:重定向输出 wc -l < /etc/passwd
wc < test.txt :输出的是数据流
wc test.txt :输出的是文本
<<:重定向追加输出 : ceshi /dev/abc << EOF … EOF

磁盘分区脚本案例

vim disk_partition.sh

fdisk -l
-------------------------------------------
#!/usr/bin/bash
#Author:Bai
#Created Time: yyyy-mm-dd hh:MM
#Script Description: harddisk partition script

fdisk /dev/sdb <<EOF
n
p
3
+512M
w
EOF

##作业
#4块磁盘 分两个区/盘
#所有的1区    做成一个LVM-LV100分区      全部空间   /data/lv100
#所有的2区    做成一个raid5分区          全部空间   /data/raid5
#要求开机挂载
#要求全部通过脚本来完成。
#线上案例:squid硬盘(CDN)  问题:IO瓶颈   解决:硬盘存储初始化脚本


shell脚本中的数学运算

expr 命令:只能做整数运算,格式比较古板,注意空格,必须是整数。
root@mips-01# expr 3 + 3
6
root@mips-01# expr 5 - 2
3
root@mips-01# expr 6 / 2
3
root@mips-01# expr 7 / 2
3
root@mips-01# expr 3 * 39
root@mips-01# expr 9 % 3
0
root@mips-01# expr 9 % 2
1

可以用来判断输入是否为整数:【结合$?使用】

root@mips-01# expr 3 + 1
4
root@mips-01# echo $?
0
root@mips-01# expr 3 + 1.1
expr: 非整数参数
root@mips-01# echo $?
2
root@mips-01# expr 7 + 1 &>/dev/null ; echo $?
0
root@mips-01# expr 7 + 1.1 &>/dev/null ; echo $?
2
root@mips-01# 

let命令和expr命令都是用来做整数运算的。

root@mips-01# let a=1+3
root@mips-01# echo $a
4
-----------------------------------------
root@mips-01# expr 3 + 1
4

还可以使用bc命令进行整数和小数的运算

yum -y install bc

bc
[root@bogon ~]# bc
bc 1.06.95
Copyright 1991-1994, 1997, 1998, 2000, 2004, 2006 Free Software Foundation, Inc.
This is free software with ABSOLUTELY NO WARRANTY.
For details type `warranty'. 
3+2
5
4+5
9
100/3
33
141*100/7966
1
4/4
1
(1+1)*3/3
2


小数计算需要设置
scale=2
100/3
33.33

计算内存使用率:

echo "当前内存使用率:`echo "scale=2;141*100/7966"|bc`%"
当前内存使用率:1.77%

使用(( ))计算:

echo $((1+1))
2
echo $((1-1 ))
0
echo $(( 100*3/2))
150
echo $(( 100%3 ))
1
echo $(( (1+2)*3 ))
9
echo $((10**3))  #开方运算
1000

脚本退出

exit NUM 退出脚本,释放系统资源,NUM代表一个整数,代表返回值。NUM:1-255

格式化输出

一个程序需要有0个或以上输入,一个或更多输出。

echo语法

功能:将内容输出到默认显示设备。
echo命令的功能是在显示器上显示一段文字,一般起到一个提示的作用。
功能说明:显示文字。
语法: echo [-ne][字符串]
补充说明:echo会将输入的字符串送往标准输出。输出的字符串间以空白字符隔开,并在最后加上换行号。
命令选项:
-n :不要在最后自动换行
-e :若字符串中出现以下字符,则特别加以处理,而不会将它当成一般文字输出:转义字符
\a :发出警告声;
\b :删除前一个字符;【必须在同一行的字符,配合-n使用】
\c :最后不加上换行符号;
\f:换行但光标仍旧停留在原来的位置;
\n:换行且光标移至首行;
\r:光标移至首行,但不换行;
\t:插入tab;
\v:与\f相同;
\插入\字符;
\nnn:插入nnn(八进制)所代表的ASCII字符;
-help:显示帮助;
-version:显示版本信息;

------输出内容不换行-----------
echo -n "Login:";read
Login:root

echo -n "Date:";date +%F
Date:2022-03-04

-------让机器输出警告声-----------
echo -e "\a\a\a\a\a\a"

------输出三个换行----------------
echo -e "\n\n\n"

----------删除一个字符------------
echo -n -e "a\b"

---------写一个倒计时脚本----------
vim daojishi.sh
#!/bin/bash
for time in `seq 9 -1 0`;do
	echo -n -e "\b$time"
	sleep 1
done	
echo 
--------输出一个水果商店清 单----------
[root@bogon test]# cat fruits.sh 
#!/bin/bash

echo -e "\t\t\t\tFruits Shop"
echo -e "\t1) Apple"
echo -e "\t2) Orange"
echo -e "\t3) Banana\n"
echo -n -e "你想吃什么?";read
[root@bogon test]# 
执行脚本输出如下:
[root@bogon test]# sh fruits.sh 
				Fruits Shop
	1) Apple
	2) Orange
	3) Banana

你想吃什么?banana
[root@bogon test]# 

颜色字体

脚本中echo显示内容带颜色显示,echo显示带颜色,需要使用参数-e
格式如下:
echo -e "\033[字体背景色; 文字颜色m字符串\033[属性效果m"


eg:
echo -e “\033[41;36m something here \033[0m”
其中41的位置代表底色,36的位置代表字的颜色,0的位置代表字体的样式【属性效果】


1、字的背景色和文字颜色之间是英文的""
2、文字颜色后面有一个m
3、字符串前后可以没有空格,如果有的话,输出也是同样有空格

下面是相应的字和背景颜色,可以自己来尝试找出不同颜色搭配:
字的颜色范围:30-37【黑、红、绿、黄、蓝、紫、天蓝、白】
字的背景色范围:40-47【黑、红、绿、黄、蓝、紫、天蓝、白】

[root@bogon test]# echo -e "\033[41;36m something here \033[0m"
 something here 
 [root@bogon test]# echo -e "\033[31m 红色字 \033[0m"
 红色字 
[root@bogon shell-04]# echo -e "\033[33m 黄色 \033[0m"
 黄色 
[root@bogon shell-04]# echo -e "\033[33m 黄色 \033[1m"
 黄色 
[root@bogon shell-04]# echo -e "\033[33m 黄色 \033[10m"
 黄色 
[root@bogon shell-04]# echo -e "\033[34m 蓝色 \033[1m"
 蓝色 
[root@bogon shell-04]# echo -e "\033[34m 蓝色 \033[0m"
 蓝色 
[root@bogon shell-04]# echo -e "\033[34m"

[root@bogon shell-04]# echo -e "\033[41;30m 红底黑色字 \033[0m"
 红底黑色字 
[root@bogon shell-04]# echo -e "\033[32m 绿色字 \033[0m"
 绿色字 
[root@bogon shell-04]# echo -e "\033[35m 紫色字 \033[0m"
 紫色字 
[root@bogon shell-04]# echo -e "\033[36m 天蓝字 \033[0m"
 天蓝字 
[root@bogon shell-04]# echo -e "\033[37m 白色字 \033[0m"
 白色字 
[root@bogon shell-04]# 

shell脚本实操学习之变量、数组_第2张图片字的背景色范围:40-47【黑、红、绿、黄、蓝、紫、天蓝、白】
shell脚本实操学习之变量、数组_第3张图片

最后面控制选项说明:

  • \033[0m :关闭所有属性
  • \033[1m :设置高亮度
  • \033[4m :设置下划线
  • \033[5m :设置闪烁
  • \033[7m :设置反息
  • \033[8m :设置消隐
  • \033[9m :设置过期线
  • \033[30m - \033[37m

设置前景色:

  • \033[40n - \033[47m :设置背景色
  • \033[nA :光标上移n行
  • \033[nB :光标下移n行
  • \033[nC :光标右移n行
  • \033[nD :光标左移n行
  • \033[x;y :设置光标位置
  • \033[9m :
  • \033[30m - \033[37m

格式化输入

read命令

默认接收键盘的输入,回车符代表输入结束
语法:
read 命令选项

  • -p :打印信息
  • -t :限定时间
  • -s :不回显
  • -n :输入字符个数

练习:模拟虚拟机的登录界面。

#!/usr/bin/bash
clear
echo -e -n "Centos Linux 7 (Core)\n"
echo -e "kernel `uname -r` an `uanme -m`\n"
echo -n -e "$HOSTNAME login:"
read acc
read -s -p "password:" pw
echo

执行效果:
shell脚本实操学习之变量、数组_第4张图片

shell变量

变量介绍

在编程中,我们总是有一些数据需要临时存放在内存,以待后续使用时快速读出。内存在系统启动的时候被按照18个单位划分为若干个块,然后统一编号(16进制编号),并对内存的使用情况做记录,保存在内存跟踪表中。

那么问题来了,1G内存有多少个1B的单位呢?

计算机的单位:
1B = 8bit
1KB = 1024B
1M = 1024KB
1GB = 1024MB
1TB = 1024GB
1PB = 1024TP
1EB = 1024PB
1ZB = 1024EB

好了,已经够大了!当然还有YB、BB更大的单位,同样进制也是1024.
1G = 102410241024-10737418248

假如你将一个1B的字符存入内存,如何读出呢?有没有一种大海捞针的感觉啊!,我们讨论一下计算机是如何通过让我们人类快速将数据提取在内存,如何从内存中读取数据的。我们研究过变量后就明白了。

变量:变量时编程中最常用的一种临时在内存中取数据的一种方式。
变量存取原理:
shell脚本实操学习之变量、数组_第5张图片
从图片可以看出,当我们在定义变量存值的时候,可以从以下方面看到变化:

  • 1)内存占用:如果存的是一个字符则占用1个字节,如果存的是字符串则是字符串的长度加1个字节长度(\0是一个特殊字符,代表字符串结束)。
  • 2)变量名与内存空间关系:计算机中会将对应的内存空间和变量名称绑定在一起,此时代表这段内存空间已经被程序占用,其他程序不可复用;然后将变量名对应在对应内存地址的空间里。

变量分类

**本地变量:**用户私有变量,只有用户可以使用,保存在家目录下的,bash_profile、bashrc文件中。
**全局变量:**所有用户都可以使用,保存在/etc/profile、/etc/bashrc文件中。
**临时变量:**只作用域本终端,在关闭终端界面或者关机以后就被释放。
**用户自定义变量:**用户自定义,比如脚本中的变量。

变量管理

定义变量

变量格式:变量名=值
shell编程中的变量名和等号之间不能有空格


变量名命名规则:

  • 命名只能使用英文字母、数字和下划线,首个字符不能以数字开头。
  • 变量名中间中间不能有空格,可以使用下划线(_)。
  • 不能使用标点符号。
  • 不能使用bash里的关键字(可用help命令查看保留关键字)。

VAR1=1
age=8
name=‘baism’
score=88.8
注意:字符串要用单引号或双引号引起来

定义变量演示:

[root@arm-00 ~]# age=8
[root@arm-00 ~]# name='baism'
[root@arm-00 ~]# score=88.8

读取变量内容

读取变量内容符:$
变量内容读出:

[root@arm-00 ~]# echo $name
baism
[root@arm-00 ~]# echo $age
8
[root@arm-00 ~]# echo $score
88.8

取消变量unset

[root@arm-00 ~]# unset name
[root@arm-00 ~]# echo $name

[root@arm-00 ~]# 

shell数组

数组介绍

一个变量只能存在一个值,但是现实中又有很多值需要存储,那么变量就有些拘谨了。比如做一个学员信息表,一个班级有50个人,每个人有6条信息,我们需要定义300个变量才能完成。恐怖,这只是一个班级的学生,一个学校呢?一个市呢?。。。
仔细想想上述的案例,一个学生有6个信息:ID、姓名、性别、年龄、成绩、班级。可不可以定义六个变量就能存储这六类信息呢?答案是肯定的。变量不行,可以用数组。

基本数组

数组可以让用户一次赋予多个值,需要读取数据时只需要通过索引调用就可以方便读出了。

数组的语法

数组名称=(元素1 元素2 元素3 ...)

数组读出

${数组名称[索引]}

索引默认是元素在数组中的排队编号,默认第一个从0开始


eg:
echo ${ARRAY1[2]}

数组赋值

方法一:一次赋一个值
ARRAY1[0]=‘2’
ARRAY1[1]=‘F’
ARRAY1[2]=‘4’
ARRAY1[3]=‘tom’
方法二:一次赋多个值
ARRAY1=(‘A’ ‘B’ ‘C’ ‘D’ ‘4’)
ARRAY2=(tom jack alice)
ARRAY3=(`cat /etc/passwd) 希望是将文件中的每一个行作为一个元素赋值给数组array3 ARRAY4=(\ls /var/ftp/Shell/for*`)
ARRAY5=(tom jack alice “bash shell”)

查看数组

declare -a:可以查看声明过的数组。

[root@arm-00 test]$ declare -a
declare -a BASH_ARGC='()'
declare -a BASH_ARGV='()'
declare -a BASH_LINENO='()'
declare -a BASH_SOURCE='()'
declare -ar BASH_VERSINFO='([0]="4" [1]="2" [2]="46" [3]="2" [4]="release" [5]="aarch64-redhat-linux-gnu")'
declare -a DIRSTACK='()'
declare -a FUNCNAME='()'
declare -a GROUPS='()'
declare -a PIPESTATUS='([0]="0")'

访问数组元素

echo ${array1[0]}:访问数组中的第一个元素
echo ${array1[@]}:访问数组中所有元素,等同于echo ${array1[*]}
echo ${#array1[@]}:统计数组中的元素个数
echo ${!array2[@]}:获取数组元素的索引
echo ${array1[@]:1}:从数组下标1开始
echo ${array1[@]:1:2}:从数组下标1开始,访问两个元素。

遍历数组

默认数组通过数组元素的个数进行遍历
echo ${array1[0]}
echo ${array1[1]}
echo ${array1[2]}
echo ${array1[3]}

方法二:
针对关联数组可以用过数组元素的索引进行遍历。

关联数组

关联数组可以允许用户自定义数组的索引,这样使用起来更加方便、高效。

定义关联数组

声明关联数组变量
declare -A ass_array1
declare -A ass_array2

[root@bogon shell-05]# bash declare_array.sh 
baidu
30
[root@bogon shell-05]# cat declare_array.sh 
#!/bin/bash

#声明一个关联数组
declare -A ass_array1

ass_array1[name]='baidu'
ass_array1[age]='30'
echo ${ass_array1[name]}
echo ${ass_array1[age]}
[root@bogon shell-05]# 

关联数组赋值

方法一:一次附一个值
数组名[索引]=变量值
ass_array1[index1]=pear
ass_array1[index2]=apple
ass_array1[index3]=orange
ass_array1[index4]=peach


方法二:一次附多个值
数组名=([索引1]=变量值 [索引2]=变量值 [索引3]=变量值 [索引4]=变量值)
ass_array2=([index1]=tom [index2]=jack [index3]=java [index4]=‘bash shell’)

[root@bogon shell-05]# bash declare_array.sh 
java
[root@bogon shell-05]# cat declare_array.sh 
#!/bin/bash

#声明一个关联数组

declare -A ass_array2=([index1]=tom  [index2]=jack [index3]=java [index4]='bash shell')
echo ${ass_array2[index3]}
[root@bogon shell-05]# 

访问数组元素

echo ${ass_array2[index2]}:访问数组中第二个元素
echo ${ass_array2[@]}:访问数组中所有元素,等同于echo ${array1[*]}
echo ${#ass_array2[@]}:获得数组元素的个数
echo ${!ass_array2[@]}:获取数组元素的索引

遍历数组

通过数组元素的索引进行遍历,针对关联数组可以通过数组元素的索引进行遍历

[root@bogon shell-05]# echo ${ass_array2[index4]}
bash shell
[root@bogon shell-05]# echo ${ass_array2[index3]}
java
[root@bogon shell-05]# echo ${ass_array2[index2]}
jack
[root@bogon shell-05]# echo ${ass_array2[index1]}
tom
[root@bogon shell-05]# 

案例分享

[root@bogon shell-05]# cat study_system.sh 
#!/bin/bash
for ((i=0;i<3;i++))
	do
		read -p "输入第$((i + 1))个人名:" name[$i]
		read -p "输入第$[$i + 1]个年龄:" age[$i]
		read -p "输入第`expr $i + 1`个性别:" gender[$i]
	done

clear
	echo -e "\t\t\t\t学员信息查询系统"

while :
    do
         cp=0
        
         read -p "输入要查询的姓名:" xm
	 [ $xm == "Q" ]&&exit
	 for ((i=0;i<3;i++))
		do
		   if [ "$xm" == "${name[$i]}" ];then
			echo "${name[$i]} ${age[$i]} ${gender[$i]}"
			cp=1
		   fi
	  done

	  [ $cp -eq 0 ]&&echo "not fonud student"	

done
[root@bogon shell-05]# 

你可能感兴趣的:(Linux,笔记,linux)