5.Linux_Shell编程

概述

什么是shell脚本:

Shell脚本是利用shell的功能所写的一个程序。这个程序是使用纯文本文件(后缀为.sh),将一些shell的语法与命令(含外部命令)写在里面,搭配正则表达式、管道命令与数据流重定向等功能。Shell脚本实际上就是Shell命令的集合

编写运行shell脚本:

  • 编写:使用vi,创建一个文本,以.sh为结尾
  • 代码:首先声明shell类型:#!/bin/bash。之后用shell命令进行编写
  • 运行:bash <脚本名>、source <脚本名>、直接脚本名(这需要脚本文件有可执行权限)

示例如下:

Shell变量

1、基本知识

shell中变量的命名要求与C类似:

  • 区分大小写
  • 不能使用程序内的保留字和内置变量(类似C不能使用关键字)
  • 只能使用数字、字母、下划线,且不能以数字开头(一般使用大写字母)

变量的分类:

变量分为:自定义变量和特殊变量。特殊变量如下

  • 环境变量:由系统维护,用于设置工作环境
  • 只读变量:用于变量值不允许被修改的情况
  • 位置变量:通过命令行给脚本程序传递参数
  • 预定义变量:bash中内置的一类变量,不能直接修改

2、变量相关操作

2.1 变量的基本操作

  • 定义赋值变量:<变量名>=<变量值>(等号两边不能有空格)
  • 取出变量值:$<变量名>
  • 取消变量定义:unset<变量名>

  • 注释:#
  • 双引号:允许引用其他变量值
  • 单引号:禁止引用其他变量值,引号中的内容为原样输出
  • 反撇号:命令替换,把命令的输出结果进行输出,与$()作用一致。

2.2 变量数组的操作

  • 数组成员初始化:<数组名>=(<数组成员值>)(等号两边没有空格,数组成员值用空格分隔)
  • 数组成员赋值:<数组名>[下标]=<变量值>。如:a[0]=10(等号两边没有空格)
  • 访问数组成员:${数组名[下标]}。假设数组名为a,以下为访问示例
  1. 显示第一个元素:${a[0]} 或者 $a
  2. 显示第n个元素:${a[n]}
  3. 显示最后一个元素:${a[-1]}
  4. 显示数组全部元素:${a[*]}  或者 ${a[@]}
  5. 显示数组元素个数:${#a[*]} 或者 ${#a[@]}

  • 删除数组:可以使用unset删除数组成员、删除整个数组
  1. 删除数组成员:unset <数组名>[下标]。删除之后,值为空。例如删除a[0],那么a[0]=空
  2. 删除整个数组:unset <数组名>

  • 显示以指定元素开始的指定个数的元素:${a[@]:起始元素:元素个数}

2.3 只读变量

只读变量常常存放传入的文件名参数,代表不能修改文件名。

只读变量不能使用unset删除,只读变量只在当前终端有效,因此可以关闭终端来强制删除

  • 定义只读变量:readonly <变量名>=<变量值>

2.4 位置变量与预定义变量

  • 传参:bash <shell脚本名> <参数>(参数用空格隔开)
  • 第一个参数:$0,值为shell脚本名
  • 第n个参数:$n,$(n)。n为多位数时用()。如:$1,$(10)
  • 总参数个数:$#。$0不进行总参数个数的统计
  • 全部传入的参数值:$@(全部参数当作一个整体)或者$*(每个参数分开是一个值)
  • 上一条指令执行的结果:$?(常用作test指令返回值的判断,$?值:test真返回0)
  • 当前进程的id号:$$

补充:$@与$*的区别验证

2.4 环境变量

  • $USER:表示用户名称
  • $HOME:表示用户的宿主目录
  • $LANG:表示语言和字符集
  • $PWD:表示当前所在工作目录
  • $PATH:表示可执行用户程序的默认路径
  • export:可以将变量指定为全局变量。默认变量只能在当前终端使用,其他的shell不能使用

2.5 局部变量与全局变量 

在shell中定义的变量默认为全局变量,在整个shell中都可以去访问。

使用local可以使变量变为局部变量。

注意:当函数为正常调用时,全局变量可以被函数外部访问。当函数是命令置换``调用时,全局变量不能被函数外部访问。

Shell语句

shell语句分为说明型语句、功能型语句、结构型语句。说明型语句就是注释;功能型语句就是shell命令,如:grep、echo等。结构型语句就是像循环、判断等语句。

1、功能型语句补充

1.1 获取键盘输入数据read

read可以获取键盘上输入的数据,并存入指定的变量中。

命令:

read <选项> 变量(多个变量用空格隔开)

选项:

  • -s:键盘输入时不显示输入的内容

  • -t <时间>:设置输入的时间,单位s。超过时间会自动退出输入

  • -p "提示":设置提示语句

1.2 算术运算命令expr

算术运算命令可以实现加(+)、减(-)、乘(\*)、除(/)、求模(%)运算

命令:expr <运算值1> <运算符> <运算值2>(运算值与运算符直接必须要有空格)

注意:expr是一个命令,所以赋值给变量运算值时需要加上``来取命令的值进行赋值

1.3 测试语句test

test可对字符串、整型、文件属性进行判断。

判断结果可以用$?来查看,当结果为真时,$?返回0;当结果为假时,$?返回1;

字符串测试

注意:在判断时,字符串需要加上双引号

  • "s1" = "s2":测试两个字符串的内容是否完全一样
  • "s1" != "s2":测试两个字符串的内容是否有差异
  • -z "s1":测试s1字符串的长度是否为0,
  • -n "s1":测试s1字符串的长度是否不为0

整型测试

  • a -eq b:测试a与b是否相等(eq:equal)
  • a -ne b:测试a与b是否不相等(ne:not equal)
  • a -gt b:测试a是否大于b(greater than)
  • a -ge b:测试a是否大于等于b(greater equal)
  • a -lt b:测试a是否小于b(less than)
  • a -le b:测试a是否小于等于b(less equal)

文件测试

文件类型与ls -l列出的文件类型符号是对应的(bcd-lsp),除了普通文件的 " - " 换成了 " f "。

具体含义在2.Linux_基础-CSDN博客的 "文件-文件类型" 章节。

  • -e name:测试一个文件是否存在(exist)
  • -d name:测试name是否为一个目录(bcd-lsp)
  • -f name:测试name是否为普通文件(bcd-lsp)                                                                     如果软连接指向的为普通文件,则该软连接也可以通过该test判断
  • -L name:测试name是否为符号链接(bcd-lsp)
  • -r name:测试name文件是否存在且为可读(rwx)
  • -w name:测试name文件是否存在且为可写(rwx)
  • -x name:测试name文件是否存在且为可执行(rwx)
  • -s name:测试name文件是否存在且其长度不为0
  • f1 -nt f2:测试文件f1是否比文件f2更新(new than)
  • f1 -ot f2:测试文件f1是否比文件f2更旧(old than)

2、结构型语句

结构型语句包括:条件测试语句(两路分支)、多路分支语句、循环语句、循环控制语句等

2.1 分支语句

2.1.1 类似 if-else
  • 表达式

if后跟判断表达式。判断表达式可以是test命令,也可以是用中括号来代替test。以判断文件是否存在为例,假设变量名为file。

方式1:if test -e $file  方式2:if [ -e $file ] (使用[ ]时,左右必须有空格)

  • 逻辑连接符

与:-a。例如:if [ -e "$file" -a -f "$file" ]  判断file值存在并且file是一个普通文件

或(第一种):-o。例如:if [ -d "$file" -o -f "$file" ] 判断file是目录或者file是一个普通文件

或(第二种):||。例如:if [ -d "$file" ] || [ -f "$file" ]  使用||时,需要有两个[ ]

非:!。例如:if [ ! -d "$file" ] 判断file不是目录

if-else语法

 注意:if 和 fi 要成对出现

if <判断表达式>
then
    条件为真时的表达式
else
    条件为假时的表达式
fi

示例:判断输入用户名是否存在

用户名存放在/etc/passwd文件中的第一列。

if-elseif-else语法

注意:if 和 elif 后都要跟一个then

if <判断表达式>
then
    if条件为真时的表达式
elif <判断表达式> 
then
    elif条件为真时的表达式
else
    条件为假时的表达式        
fi

示例:判断输入的文件类型

2.1.2 类似 switch-case

当模式为多个时,可以用" | "来进行连接。

当模式值为*时,类似switch-case中的default

语法:

case 字符串变量 in
    模式1)   #多种情况时,可以用 | 来连接
        代码
        ;;   #这类似switch-case里的break ;;必须加,否则会报错
    模式2)
        代码
        ;;   #最后一个模式可以省略;;
esac

 示例:将学生成绩进行分类,80~100的为A,0~79的为B。其余成绩是错误数据

2.2 循环语句

2.2.1 类似 for

for从"表"中拿数据赋值给"变量",拿一个数据循环一次,循环次数就是"表"中的数据个数。

for后跟的可以是 "变量 in 表" 这种形式,也可以是(( ))类似C语言语法的形式。

语法:

for 变量 in 表
do
    代码xxx
done

示例1:获取输入的参数

示例2:for的用法

2.2.2 类似 while

while后跟的表达式,可以是if后那种[ ]形式,也可以为(( ))这种C语言语法形式。

语法:

while 表达式
do
    代码xxx
done

示例:for的用法

2.2.3 break、continue

break与continue的使用与C中的完全一致。区别点是代码后面不需要加分号。

2.3 退出exit

当shell脚本执行到exit时,代表该脚本退出,后面的脚本代码不再执行

2.4 函数

语法:

function 函数名(){
    代码段
    return xxx #没有return值可以不写
}

获取return值:

在调用函数之后,使用$?来获取return的数值。注意:函数只能return整型数字

获取函数中打印到标准输出(终端)的值:

使用 `函数名` 来获取函数中打印到标准输出的值。

函数传参:

函数传参就是直接在函数名后面加入参数即可,函数获取参数是通过位置变量来获取。

局部变量与全局变量:

在shell中定义的变量默认为全局变量,在整个shell中都可以去访问。

使用local可以使变量变为局部变量。

注意:当函数为正常调用时,全局变量可以被函数外部访问。当函数是命令置换``调用时,全局变量不能被函数外部访问。

  • 33
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值