Shell编程

1、shell 概述

A、是什么?

shell 是一门计算机语言,和 python | Java 一样,都可以编写程序
A-1、shell字面意思: (相对核而言),核:指操作系统,shell 是保护操作系统的
A-2、计算机操作系统只能识别 0 和 1 组成的机器码,现在我们是通过GUI|CLI 来间接操作操作系统
  GUI(图形化界面) | CLI(命令行) 在用户与操作系统之间,相当于桥梁、中介的作用,结构上看,GUI和CLI 保护操作系统
A-3、GUI 与 CLI 就是通过 Shell 实现的

B、为什么?

通过shell按照需求编写一些程序

C、怎么用?(linux)

C-1、分类
  第一类:GUI样式的shell
  第二类:CLI样式的shell(重点)
  专指: Linux 下的 shell 编程
C-2、流程
  1)、创建一个文本文档,后缀名是 .sh 文档名要做到见名知意
  2)、再在文本文件中录入一个命令
    echo "xxxx" 在命令行模式下直接输出数据
    规范:第一行固定格式,这是解释器声明: #!/bin/bash
    作用:指定脚本解析的解释器
  3)、执行 .sh 文件(.sh又称为shell 脚本,里面放DOS命令)
    方式1: sh(bash) shell文件
    方式2: 绝对路径(/xxx/yyy/abc.sh) 或 相对路径(./abc.sh),注意:开启所有权限 chmod 777 abc.sh
    方式3: source abc.sh(source 相当于 ./)

D、练习
练习1:在命令行输出当前所在目录:pwd

2、shell 语法: 注释

A、是什么?

注释是程序中非功能性说明文本

B、为什么?

增强程序的易读性,易维护性

C、怎么用?

注释量占到代码总量的 30% -- 50%
单行注释(常用):一次只注释一行
格式: # 注释文本
多行注释(了解,基本不用):一次可以注释多行
:<<自定义的标记
  第一行注释
  第二行注释
  .....
自定义标记

3、shell 语法: 变量

A、是什么?

程序=数据+数据操作
变量就是数据的载体,变量之所以称之为变量,是因为其中的值可以改变

B、为什么?

变量为数据设置一个引用,以后再使用这个数据时,可以通过引用获取数据

C、怎么用?(重点)

变量创建:
  格式: 变量名="变量值"
  注意1:变量名
    a)、不能数字开头
    b)、变量名不能有空格这种特殊字符
    c)、起名做到见名知意
    d)、变量名不要使用关键字
  注意2:赋值符号
    =左右两侧不要有空格
  注意3:变量值
    a)、变量值可以不使用引号,但是如果有空格,必须使用 "xxx" 或者 'xxx'
    b)、"xxx" 和 'xxx' 的区别,变量之间赋值时,如果是 变量2="${变量1}",那么赋的是变量1的值
    如果是 变量2='${变量1}' 只是赋值了变量1的调用格式,就是echo ${变量2} 返回的是${变量1},而不是变量1的值
变量查询:
  格式:"${变量名}" ----- 标准格式
  注意:其他格式(不建议使用):${变量名} 或者 $变量名
变量修改:
  格式:同变量新增
变量删除:
  格式:unset 变量名

D、变量分类

D-1、本地(局部)变量
  只有当前 shell 可以使用的变量
D-2、全局变量(静态变量)(了解)
  被多个 shell 共享的变量
  需求:如何将本地变量转换成全局变量
    思想:将本地变量设置为全局变量就是要将本地变量导出到共享空间
    格式: export 局部变量
  查询全局变量: env
  注意1:如果是全局变量,建议变量名所有字母都大写
  注意2:全局变量要慎用
D-3、内置变量(特殊变量)
  需求:编写shell动态获取某个目录下的子级(要获取的目录不一定)
  实现流程:
  1)、shell 调用时,可以传入要操作的目录
    格式: sh abc.sh 某个目录
  2)、shell 执行时,可以获取调用传入的目录
    格式:ls $1 (代表传入的第一个参数)
上述流程其实就是传参以及参数解析的过程,这个参数就可以称之为内部变量

特殊变量语法总结:
  应用场景,程序执行时有些数据是可变的,可以调用脚本时,传入这些可变数据,脚本中解析获取
  调用格式: sh xxx.sh 参数1 参数2 参数3 .....
  解析格式: $N 获取第 N 个参数
  优 点: 动态传值,更灵活
  注 意: $N 获取第 N 个参数,但是 N 最大就到 9
    $0 获取脚本文件名
    $* 获取所有参数
    $# 获取参数个数
D-4、扩展:读取键盘录入
  需求:编写shell动态获取某个目录下的子级(目录不一定,要让调用者指定)
  格式: read_ -p_"提示语句:"_变量名 (注意:_是空格!!!!)
  作用:执行到此时,程序挂起,等待用户录入数据,录入数据后,回车,录入的数据会赋值给变量
  优点:动态获取数据,更灵活!!!!!

E、变量特殊赋值(记住)

需求:将某个命令的结果赋值给一个变量
格式:变量名=`命令`

F、练习
练习1:使用shell脚本,输出当前所在的目录

知识点:将命令结果赋值给变量

练习2:计算/etc目录下有多少个文件,用shell脚本实现

新知识点:获取某个目录下子级个数
固定格式:ls 目录 | wc -l

练习3:实现统计用户指定目录下的文件个数,用 shell 脚本实现

知识点:怎么动态获取数据?(特殊变量或者读取键盘录入)

4、shell 语法: 运算符

A、是什么?

是变量执行运算时使用的一些特殊符号

B、为什么?

因为程序中频繁使用算数运算、逻辑运算、比较运算....等算法

C、怎么用?

运算符分类
C-1、算数运算符
  格式: $((数学表达式))
  运算符: + - * / % ----> 加减乘除取余
  注意: 一般计算机语言中除法运算只取商
C-2、比较运算符:返回的是 boolean 值(特殊: 0为true 1为false)
  格式: [ 表达式 ] ---- 注意:[] 中有两个空格,两个空格中添加表达式
  查看结果: $?
  运算符: 不能直接使用 > < >= <= == !=
  使用对应的参数 -gt(>) -lt(<) -ge(>=) -le(<=) -eq(==) -ne(!=) 记住
    g = greater
    t = than
    l = less
    e = equals
    n = not
C-3、逻辑运算符:返回 boolean 值(特殊: 0为true 1为false)
  格式: [ 表达式 ]
  查看结果: $?
  运算符: -a 与-o或 !非
C-4、字符串比较:返回 boolean 值
  格式: [ 表达式 ]
  查看结果: $?
  运算符: == 判断两个字符串内容是不是一样
  != 判断两个字符串内容是不是不一样
   -z 判断单个字符串长度是不是0(判断字符串是不是空)
C-5、文件判断:返回 boolean 值
  格式: [ 表达式 ]
  查看结果: $?
  运算符:-d: 判断是不是文件夹
      -f: 判断是不是文件
      -e: 判断是不是存在
  变体:
    test -参数 路径 等价于 [ -参数 路径 ]
    例如:test -d ${myDir} 等价于 [ -d ${myDir} ]

D、练习
练习1:判断 /home/admin(/root)目录是否为空

思路:现获取目录子级文件个数,判断是否大于 0

练习2:通过用户输入任意目录判断是否为空

5、shell 语法: 函数(方法)

A、是什么?

程序=数据+数据操作
变量是数据的载体,函数是数据操作的载体,是程序中最小的功能(封装)单元,在函数中一般会封装一个具有特定功能的实现

B、为什么?

优点1:代码结构更规整,易维护 易读
优点2:实现了功能复用

C、怎么用?

C-1、函数声明
function(可选) 函数名(){
  函数体
}
C-2、函数调用
函数名
C-3: 注意
1、函数不调用不执行(所有计算机语言通用)
2、顺序上必须先声明再调用(弱类型计算机语言的特点)
C-4、函数分类
类型1:无参数无返回值
类型2:有参数
  声明语法:获取参数使用
    $N : 获取第 N 个参数,N必须小于等于 9
    $0:脚本文件名
    $*:所有参数
    $#:参数个数
  调用语法:参数传递
    函数名 参数1 参数2 .....
  如下图:

Shell编程_第1张图片
函数声明与调用

类型3:有返回值(了解)
  声明语法:
    函数名(){
      ....
      return xxx;
    }
  调用语法:
    函数名
    $? 查看结果
  注意:函数的返回值在 shell 中两种:
    return 0 : 函数调用正常
    非0 : 函数执行有误
  在shell中的函数中的变量在大括号外面也能调用

D、练习
练习1:读取键盘录入,录入长方形的长和宽,编写求周长和面积的函数,调用并输出周长和面积的值
Shell编程_第2张图片
求长方形周长和面积

6、shell 语法: 流程控制(重点)

A、是什么?

就是控制代码的执行顺序,让代码实现分支或循环执行

B、为什么?

组织多样的业务逻辑

C、分类?

分支: if + case
循环: for + while

7、shell 语法:流程控制分支实现之 if

A-1、格式1(单分支)

语法:
  if [ boolean表达式 ]
  then
      code......
  fi

举例:

(需求: 录入年龄,判断是否成人,如果成人了输出"成年人")

A-2、格式2(双分支)
语法:

  if [ boolean表达式 ]
  then
    code.....
  else
    code.....
  fi

举例:

(需求: 录入年龄,判断是否成人,如果成人了输出"成年人",否则输出未成年)

A-3、格式3(多分支)

语法:
  if [ boolean表达式 ]
  then
    code....
  elif [ boolean表达式 ]
  then
    code....
  elif 可以出现多次
  else
    code....
  fi

举例:

​ (需求: 录入年龄,如果小于18岁,输出未成年,如果大于等于18岁小于等于30岁,输出青年,如果大于30岁小于50岁,输出中年,否则,输出老年)

B、练习
练习1:判断用户输入的用户名和密码是否为admin 123456,如果是则提示登录成功,否则提示失败

知识点:if else +运算符

练习2:输入数字,判断是否大于0,如果大于0则将该数字-1并输出,否则+1输出
练习3:判断用户输入的目录是否存在,如果存在则统计目录下的文件个数,否则提示用户该目录不存在
练习4:判断学生的成绩,大于90-100提示优秀,80-90之间提示良好,70-80之间则提示一般,60-70之间提示 及格。其他则提示不及格
练习5:判断用户输入的内容是否为空,为空则提示,不为空则判断是否为目录,不为目录则判断是否为文件,否则提示错误信息

知识点:多分支

8、shell 语法:流程控制分支实现之case(了解)

A、格式

语法:
  case 变量(用户输入的数据) in
  值1)
    code;;
  值2)
    code;;
  值3)
    code;;
  .....
  *)
    code;;
  esac

举例:

(需求:模拟游戏级别选择,读取键盘录入的数字,如果是数字1,那么输出简单, 如果是数字2,那么输出一般,如果是数字3输出困难,其他输出数据有误)
注意:
  1、case 能实现的 if elif 也能实现
  2、if elif 能实现的,case不一定能实现了
  3、语法上 if elif 更简单
  4、但case执行效率高

B、练习
练习1:输入一个序号,判断该用户选择哪款产品,A:笔记本 B:电饭煲 C:小台灯
练习2:请输入对客服的满意度,【0-3】不满意,【4-6】满意,【7-9】非常满意 (了解)

case 也可以执行区间判断,但是区间范围局限于: 0 - 9
区间格式 :[开始数字-结束数字]

9、shell 语法:流程控制循环实现之for

A、格式

语法:
  for 变量名 in 列表(v1 v2 v3 ......)
  do
    code.....#循环体
  done

举例:

(需求:遍历(迭代) 1-10之间所有整数)


Shell编程_第3张图片
for循环

B、注意
seq 命令优化 for 循环
格式1: seq 参数NUM ---> 默认遍历 [1-NUM] 之间的所有整数
  例如:for ele in `seq 15`......

格式2: seq 参数NUM1 参数NUM2 ----> 遍历 [NUM1-NUM2]之间的所有整数

格式3: seq 参数NUM1 参数NUM2 参数NUM3 ----> 遍历 [NUM1-NUM3] 之间的整数,但是每次递增 NUM2 值,不指定 NUM2 每次默认递增1, NUM2 又称之为步进值

C、练习

求1-100之间的和


Shell编程_第4张图片
求1-100之间的和

10、shell 语法:流程控制循环实现之while

A、格式

语法:
  while [ boolean表达式 ]
  do
    code.....
  done

举例:

(需求:遍历 1-10之间所有整数)


Shell编程_第5张图片
遍历1-10
B、练习

求1-100之间的和


Shell编程_第6张图片
求1-100之间的和
综合练习:输入一个目录,判断目录是否存在,如果不存在则给出提示,如果存在则提示输入要创建的文件名,(前提:要先进入目录)判断创建的文件是否存在,如果不存在,则继续创建,否则提示该文件已经存在

需求:目录操作与文件操作,分别两个函数实现,两个函数中分别实现业务逻辑(分支语句)

11、shell 语法其他:重定向

A、是什么?

可以将命令产生的数据保存到磁盘文件

B、为什么?

一种序列化(持久化)机制,可以持久的保存数据

C、怎么用?

格式1: 命令 1>> 磁盘文件 (将正常结果输出到文件)
  例如:ls /usr 1>> hello.txt
格式2: 命令 2>> 磁盘文件 (将错误结果输出到磁盘文件)
  例如:lsxz /usr 2>> hello.txt

12、shell 语法其他:数组

A、是什么?

数组也是变量,但是是特殊的变量,一般变量只能存储一个值,而数组可以存储多个值

B、为什么?

因为数组功能更强大

C、怎么用?

数组创建
  变量名=(值1 值2 值3 .... )
数组查询
  查某个元素: ${数组名[索引]}---->索引从 0 开始
  查询所有元素: ${数组名[*]} 或者 ${数组名[@]}
  查询元素个数: ${#数组名[*]} 或者 ${#数组名[@]}
数组修改
  变量名[索引]=新值
数组删除
  unset 数组名(同变量删除)

D、应用

集合循环遍历数组元素


Shell编程_第7张图片
用数组遍历

你可能感兴趣的:(Shell编程)