1.1 shell 简介

Shell 是一个命令行解释器,它接收外层应用程序/用户命令,然后调用操作系统内核,进而控制硬件。
image.png
Shell 还是一个功能强大的变成语言,易编写、易调试、灵活性强

1.2 shell 解析器

image.png
shell 脚本特点是由 “.sh” 结尾,常用的解析器为 sh 、bash ,除此之外还有 nologin 、dash 、 tcsh 、csh 等

1.2.1 Centos 默认解析器为bash

image.png

1.2.2 bash 和 sh 的关系

  • sh 是 bash 的软链接
  • 在一般的linux系统当中(如redhat),使用sh调用执行脚本相当于打开了bash的POSIX标准模式
  • 也就是说 /bin/sh 相当于 /bin/bash —posix

所以,sh跟bash的区别,实际上就是bash有没有开启posix模式的区别
image.png

1.3 shell脚本入门

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

1.3.1 脚本格式

脚本以 #!/bin/bash 开头(作用是指定解析器,例如此处指定 bash 解析器)
也可用 /bin/bash/env bash|python|perl

1.3.2 案例1:编写一个shell脚本

1.3.2.1 需求

创建一个shell脚本,输出 “helllo world!”
image.png
脚本内容:

  1. #!/bin/bash
  2. echo "helloworld!"

1.3.2.2 执行脚本

可以看到不管用 bash+相对路径/绝对路径 还是 sh+相对路径/绝对路径 都可以运行脚本,相对路径和绝对路径运行也没有区别
image.png

image.png
原因是使用第一种命令执行脚本时,是直接使用 sh 或 bash 解析器调用脚本,因此不需要权限。使用相对路径执行因为是自己执行所以需要执行权限。
可以用 chmod 赋予权限,然后再次
image.png

1.3.3 案例2:多命令操作

1.3.3.1 需求

在 /home/atguigu 目录下创建一个 banzhang.txt , 在 banzhang.txt 中增加 “I love cls”
image.png
脚本内容:

  1. #!/bin/bash
  2. mkdir -p /home/atguigu
  3. cd /home/atguigu
  4. echo I love cls >> banzhang.txt

常用时间命令

  • date +%Y-%m-%d #年(以四位数字格式打印年份)月日
  • date +%y-%m-%d #年(以两位数字格式打印年份)月日
  • date +%T #年(以四位数字格式打印年份)月日
  • date +%H:%M:%S #小时分钟秒
  • date +%T #小时分钟秒
  • date +%w #一周中的第几天
  • date +%W #一年中的第几周
  • date -d “+1 hour” #一个小时后
  • date -d “-1 hour” #一个小时前
  • date -d “+1day” #一天后
  • date -d “-1 day” #一天前

1.4 Shell 变量

1.4.1 系统变量

1.4.1.1 常用系统变量

$HOME、$PWD、$SHELL、$USER 等
image.png

1.4.2 自定义变量

1.4.2.1 基本语法

1.4.2.1.1 定义变量: 变量=值

image.png

1.4.2.1.2 重新赋值 变量=值

image.png

1.4.2.1.3 撤销变量 : unset 变量

image.png

1.4.2.1.3 声明静态变量: readonly 变量 , 注意:不能unset

image.png
只有重启才能撤销

1.4.2.1.4 将局部变量提升为全局变量: export 变量

image.png
可以看到第一次执行脚本无法显示 变量D 的值,因为此时它还是一个局部变量

1.4.2.2 变量定义规则

  • 变量名称可以由字母、数字和下划线组成,但是不能以数字开头,环境变量名建议大写
  • 等号两侧不能有空格
  • 在 bash 中, 变量默认类型都是字符串类型,无法直接进行数值运算
  • 变量的值如果有空格,需要使用双引号或单引号括起来

1.4.3 特殊变量:$n

1.4.3.1 基本语法

$n 功能描述: n 为数字,$0代表该脚本名称,$1-$9代表第一到第九个参数,十以上的参数需要用大括号包含,如${10}

1.4.3.2 案例3:参数练习 $n

image.png

1.4.4 特殊变量:$

1.4.4.1 基本语法

$# 功能描述:获取所有输入参数个数,常用于循环

1.4.4.2 案例4:参数练习 $

image.png

1.4.5 特殊变量:$*、$@

1.4.5.1 基本语法

$* 功能描述:这个变量代表命令行中所有的参数, $把所有的参数看成一个整体
$@ 功能描述:这个变量也代表命令行中所有的参数,不过 $@ 把每个参数区分对待

1.4.5.2 案例5:参数练习 $*、$@

image.png

1.4.6 特殊变量: $?

1.4.6.1 基本语法

$? 功能描述:最后一次执行的命令的返回状态,如果这个变量的值为 0 ,证明上一个命令正确执行;如果这个变量的值非 0 (具体是哪个数,由命令自己来决定),则证明上一个命令执行不正确了

1.4.6.2 案例6:参数练习 $?

image.png

1.5 运算符

1.5.1 基本语法

  • “$((运算式))”或”$[运算式]”
  • expr +、-、*、/、% 加、减、乘、除、取余

注意:expr 运算符间要有空格

1.5.2 案例6:加减法及混合运算

3+2
image.png

3-2
image.png

(2+3)*4
image.png

采用 $[运算符]计算(2+3)*4
image.png

1.6 条件判断

1.6.1 基本语法

[ condition ](注意 condition 前后要有空格)
注意: 条件非空即为true,[ atguigu ]返回 true ,[] 返回 false

1.6.2 常用判断条件

(1) 两个整数之间比较
= 字符串比较
-lt 小于 (less than -le 小于等于(less equal
-eq 等于(equal-gt 大于(greater than
-ge 大于等于(greater equal-ne 不等于 (not equal
(2) 按照文件权限进行判断
-r 有读的权限(read -w 有写的权限(write
-x 有执行的权限 (execute
(3) 按照文件类型进行判断
-f 文件存在并且是一个常规的文件(file
-e 文件存在(existence-d 文件存在并是一个目录(directory

1.6.3 案例7:判断条件

(1) 23 是否大于等于 22
image.png
返回是0,说明上一条命令正确执行

(2) 23 是否小于等于 22
image.png
非0即为flase

(3) helloworld.sh 是否有写权限
image.png

(4) /home/atguigu/cls.txt 目录中的文件是否存在
image.png

(5) /home/atguigu/banzhang.txt 目录中的文件是否存在
image.png

(6) 多条件判断( && 表示前一条命令执行成功时,才执行后一条命令, || 表示上一条命令执行失败后,才执行下一跳命令)
image.png

1.7 逻辑判断

1.7.1 单if语句

适用范围:只需要一步判断,条件返回真干什么或条件返回假干什么
语句格式

  1. if [ condition ] # condition 值为 true 或 flase
  2. then
  3. commands
  4. fi

翻译成汉语大致意思时:

  1. 假如 条件为真
  2. 那么
  3. 执行 commands 代码块
  4. 结果

1.7.2 案例8:文件夹是否存在

假如在 /tmp下没有 /abc 这个文件夹,那么就创建一个
image.png

1.7.3 if-then-else 语句

适用范围:条件为真干什么,条件为假干什么

  1. if [ condition ]
  2. then
  3. commands1
  4. else
  5. commands2
  6. fi

翻译成中文大致是:

  1. 假如条件为真
  2. 那么
  3. 执行 commands1 代码块
  4. 否则
  5. 执行 commands2 代码块
  6. 结束

1.7.4 案例9:判断登陆用户

假如登陆用户是root,输出管理员你好
假如登陆的是普通用户输出,guest,你好
image.png
image.png

1.7.5 if-then-elif语句

适用范围,适用于两个以上的判断结果,也就是多余一个以上的判断条件

  1. if [ condition ]
  2. then
  3. commands1
  4. elif [ condition 2]
  5. then
  6. commands2
  7. ......
  8. else
  9. commandsX
  10. fi

语句翻译成汉语大致为:

  1. 假如 条件1 为真
  2. 那么
  3. 执行代码块1
  4. 假如 条件2 为真
  5. 那么
  6. 执行代码块2
  7. 以此类推的N个条件及对应的执行代码块
  8. 否则 [ 以上所有条件没有一个满足的 ]
  9. 执行代码块X
  10. 结束

1.7.6 案例10:判断两个整数的关系

嵌套写法
image.png
非嵌套写法
image.png

1.7.7 if 的高级用法

(1)双小圆括号中可以植入数学表达式做数学运算
image.png

(2)双方括号可以在条件中使用通配符,做字符串匹配
image.png

编写脚本思路

例如:编写一个自动安装 nginx 的脚本
先用中文写出思路,再按照思路进行编写
image.png
image.png

1.8 shell循环控制语句

1.8.1 sleep N 脚本执行到该步休眠 N 秒

image.png

1.8.2 continue 跳过循环中的某次循环

当按顺序输出 1-9 跳过 5 ,命令如下:
image.png

1.8.3 break 退出循环

要求用户输入一个字母,当输入 Q 时退出
image.png

循环输出数字,间隔 3 秒
image.png
image.png

当循环执行一次后,停止从里向外数第二层循环
image.png
image.png

1.9 shell流程控制-for循环语句

  • for循环
  • for语法
  • 循环控制

脚本在执行任务的时候,总会遇到需要循环执行的时候,比如说我们需要脚本每隔五分钟执行一次 ping 的操作,除了计划任务,我们还可以使用脚本来王城,那么我们就用到了循环语句。

1.9.1 for循环介绍

很多人把 for 循环叫做 条件循环 ,或者 for i in,其实前者说的就是 for 的特性,for 循环的次数和给予的条件是成正比的,比如给 for 十个条件, for 就循环十次;后者说的是 for 语句。

1.9.2 for语法

1.9.2.1 for语法(1)

  1. for var in value1 value2 ......
  2. do
  3. commands
  4. done

1.9.2.2 案例11:利用for循环输出 1-9

image.png

1.9.2.3 for语法(2)

C 式的 for 命令

  1. for ((变量;条件;自增减运算 ))
  2. do
  3. 代码块
  4. done

1.9.2.4 案例12:利用 for 循环输出1-9(2)

image.png

for循环使用多个变量

image.png

for的赋值

image.png

循环的优点

  • 节省内存
  • 结构更清晰
  • 节省开发时间

    1.10 shell 流程控制- while 循环语句

  • while循环介绍

  • while循环语法
  • while实例

1.10.1 while 循环介绍

while 在 shell 中也是负责循环的语句,和 for 一样 。因为功能一样,很多人在学习和工作中的脚本遇到循环到底该使用 for 还是 while 呢?很多人不知奥,就造就了有些人一遇到循环就一味的用 for 或 while 。我认为可以按照这种思路来使用,既知道循环次数就可以用 for ,比如一天需要循环 24 次;如果不知道代码要循环多少次,那就用while ,比如猜数字,每个人猜对一个数字的次数都是不能固定的,也是未知的。

1.10.2 while 循环语法

  1. while [ condition ] #注意,条件为真while才会循环,条件为假,停止循环
  2. do
  3. commands
  4. done

1.10.3 实例13:while 基础语法练习

(1)如果输出的值大于 0 ,则会每三秒输出一次大于
image.png

(2)只有输入“root”才会跳出程序,否则一直循环
image.png

(3)只要 没有 /tmp/baism 这个文件就一直回复 “not found”,有就直接跳出
image.png

(4)丈母娘选女婿
image.png

1.10.4 shell流程控制-while循环嵌套

可以嵌套 if for while
循环控制 sleep break continue

输出从一到九
image.pngimage.png


1)continue跳过

跳过5继续输出
image.png
image.png

2)break 退出

跳过5,且当输出到10时退出
image.png
image.png

3) sleep 循环节奏

让每输出一个数字三秒后再输出第二个
image.png

4)whlie嵌套for

九九乘法表
image.png
image.png

1.11 until 语句

  • until介绍
  • until语法
  • 案例分享

1.11.1 until介绍

和whlie正好相反,until是条件为假开始执行,条件为真停止执行

1.11.2 until语法

  1. until [ condition ]
  2. do
  3. commands代码块
  4. done

1.11.3 案例14:until练习

遍历10 - 20
image.png
image.png

使用 while 循环打印1-10,使用 until 打印11-20
image.png
image.png

1.12 shell流程控制-case多条件分支语句

  • case介绍
  • case语法
  • shell特殊变量

1.12.1 case介绍

在生产环境中,我们总会遇到一个问题需要根据不同的状况来执行不同的预案,那么我们要处理这样的问题就要首先根据可能出现的i情况写出对应的预案,根据出现的情况来加载不同的预案

1.12.2 case语法

  1. case 变量 in
  2. 条件1
  3. 执行代码块1
  4. ;;
  5. 条件2
  6. 执行代码块2
  7. ;;
  8. ......
  9. esac
  10. 注意:每个代码块执行完毕要以 ;; 结尾代表结束,case结尾要以倒过来写的esac来结束

1.12.3 案例15:case练习

输入1显示”haha“,输入2显示”hehe:”,输入其他数显示“1|2”
image.png
image.png

拜访丈母娘家遇到不同的人该说的话
image.png
image.png

1.12.4 shell 特殊变量

  • $*:代表所有参数,其间隔为 IFS 内定参数的第一个字元
  • $@:与*类似,不同之处在于不参照 IFS
  • $#:代表参数数量
  • $:执行上一个命令的返回值
  • $$:本身的 Process ID
  • $:执行上一个背景指令的 PID
  • $_:显示出最后一个执行的命令
  • $N:shell的第几个外传参数

1.13 Shell 函数

  • 函数介绍
  • 函数语法
  • 函数实例

1.13.1 函数介绍

在写代码时,很多人习惯从头写到结束,完成以后在一起测试,但是到测试阶段才发现错误很多,很难更改。
所以引入了函数这个概念,把代码模块化,一个模块实现一个功能,哪怕是一个很小的功能都可以,这样的话我们写代码就会逻辑上比较简单,代码量比较少,排错简单,这也就是函数的好处。
函数默认不会执行,除非调用。
函数的优点:

  • 代码模块化,调用方便,节省内存
  • 代码模块化,代码量少,排错简单
  • 代码模块化,可以改变代码的执行顺序

1.13.2 函数的语法

  1. 语法一:
  2. 函数名(){
  3. 代码块
  4. return N
  5. }
  6. 语法二:
  7. function 函数名{
  8. 代码块
  9. return N
  10. }

1.13.3 案例016:函数应用
定义两个函数并调用
image.png
image.png

1.14 shell 数组

  • 数组介绍
  • 基本数组
  • 关联数组
  • 案例解析

1.14.1 数组介绍

一个变量只能存储一个值,但是现实中又有很多值需要存储,那么变量就有些拘谨了。比如做一个学员信息表,一个班 50 个人,每个人 6 条信息 ,我们需要定义 300 个变量才能完成。如果把一个学生的信息分为六个部分:ID、姓名、性别、年龄、成绩、班级。如果使用数组的话只要对应定义 6 个变量就可以了。

1.14.2 基本数组

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

1.14.2.1 数组语法

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

1.14.2.2 数组读出

  1. ${数组名称[索引]}
  2. 索引默认时元素在数组中的排队编号,默认第一个从 0 开始

1.14.2.3 数组赋值

方法一:一次赋一个值

  1. ARRAY1[0]='E'
  2. ARRAY1[1]='F'

方法二:一次赋多个值

  1. ARRAY1=('a' 'b' 'c' 'd')

1.14.2.4 查看数组

  1. declare -a #查看系统声明过哪些数组

1.14.2.5 访问数组元素

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

1.14.2.6 遍历数组

默认数组通过数组元素的个数进行遍历

  1. #echo ${ARRAY1[0]}
  2. pear
  3. #echo ${ARRAY1[1]}
  4. apple
  5. #echo ${ARRAY1[2]}
  6. orange
  7. #echo ${ARRAY1[3]}
  8. peach

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

1.14.3 关联数组

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

1.14.3.1 定义关联数组

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

1.14.3.2 关联数组赋值

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

方法二:一次赋多个值
ass_array2=([index1]=tom [index2]=jack[index3]=alice[index4]=’bash shell’)

1.14.3.3 查看数组

declare -A
declare -A ass_array1=’([index4]=”peach” [index1]=”pear” [index2]=”apple” [index3]=”orange”)’
declare -A ass_array2=’([index4]=”bash shell” [index1]=”tom” [index2]=”jack” [index3]=”alice”)’

1.14.3.4 访问数组元素

echo ${ass_array2[index2]} 访问数组中的第二个元素
echo ${ass_array2[@]} 访问数组中所有元素
echo ${ass_array1[*]} 访问数组中所有元素
echo ${#ass_array2[@]} 获得数组元素的个数
echo ${!ass_array2[@]} 获得数组元素的索引

1.14.3.5 遍历数组

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

  1. #echo ${ass_array2[index1]}
  2. tom
  3. #echo ${ass_array2[index2]}
  4. jack
  5. #echo ${ass_array2[index3]}
  6. alice
  7. #echo ${ass_array2[index4]}
  8. bash shell

1.14.4 案例16:学员信息系统
image.png
image.png