一、概述
Shell 是计算机操作系统中用户与操作系统内核之间的接口层,它提供了一种方式让用户能够通过命令行界面(CLI)与操作系统交互。Shell 可以被视为一个命令解释器,它接收用户输入的命令,解析这些命令,并将它们传递给操作系统以便执行。Shell 也会显示命令的执行结果,以及提供一系列的脚本语言功能,如变量、循环、条件判断和函数,使得用户能够编写脚本来自动化任务。
Shell脚本运行过程:
常见的 Shell 命令解释器:
-
Bourne Shell (
sh
):UNIX 系统中最古老的 shell,是许多其他 shell 的基础。 -
C Shell (
csh
):由贝尔实验室开发,提供了更类似于 C 语言的语法结构。 -
Korn Shell (
ksh
):结合了 Bourne Shell 和 C Shell 的特性,提供了更多的功能和改进。 -
Bash Shell (
bash
):GNU 项目的一部分,是 Linux 和 macOS 中最常用的 shell,提供了丰富的功能和广泛的脚本支持。 -
Z Shell (
zsh
):一个高度可配置的 shell,提供了许多高级功能,如自动补全和语法高亮。 -
PowerShell:Microsoft 开发的 shell 和脚本语言,主要用于 Windows 系统,也支持 Linux 和 macOS。
查看自己linux系统的默认解析:echo $SHELL
二、Shell脚本编写规范
首行设置Shell解释器类型,语法如下:
#!/bin/bash
单行注释:
#注释内容
多行注释:
:<<!
#注释内容1
#注释内容2
!
Shell脚本编写Hello World案例
helloworld.sh文件内容(注意文件以.sh结尾)
脚本文件执行
注意:
当我执行 ./helloworld.sh的时候,报错了,第一次报错是因为权限不足,这时候修改一下文件权限就行;第二次报错/bin/bash/: bad interpreter: Not a directory
。这个错误表明脚本的第一行(称为 shebang 行)指向的解释器路径有问题。在文件的开头我编写的是#!/bin/bash/,这里编写错了,正确的应该是#!/bin/bash
三、环境变量
有Linux基础的同学都知道当我们在shell终端执行cd命令的时候,实际上执行的就是/usr/bin/cd这个程序文件,那么我们是否会有这样的疑问,为何我们无论在哪个目录下都能执行cd命令?这其实就是环境变量的作用;我们可以执行env来查看当前的系统环境变量:
Linux知识回顾:
如果想输出特定的环境变量,可以执行echo $环境变量名:
设置临时环境变量export 变量名=变量值:
永久生效:
定义与使用
1.局部变量
在一个shell脚本文件中定义的变量只能给当前的脚本文件使用,这个变量就叫局部变量
定义语法:
var_name=name
语法规则:
1.变量名称可以有字母,数字和下划线组成,但是不能以数字开头
2.等号两侧不能有空格
3.在bash环境中,变量的默认类型都是字符串类型,无法直接进行数值运算4.变量的值如果有空格,必须使用双引号括起来
5.不能使用shell的关键字作为变量名称
下面展示变量的定义与访问:
2.常量
定义之后就不能修改
语法readonly 变量名
3.全局变量
在A.sh脚本中定义的变量能被B.sh脚本所访问
语法 export 变量名
demo1.sh:
#!/bin/bash
var_env="张三"
export var_env
sh demo2.sh
demo2.sh
#!/bin/bash
echo "输出环境变量var_env,值为${var_env}"
在终端执行sh demo1.sh
总结:
局部变量定义:变量名=变量值
常量定义:readonly 变量名
全局变量定义:export 变量名
查询变量:$变量名 、${变量名}
删除变量:unset 变量名
4.特殊变量
Shell 提供了一些预定义的特殊变量,如:
$0
:脚本的名称。$1
,$2
, ...:脚本的参数。$#
:脚本参数的数量。$?
:最后执行的命令的退出状态。$!
:最后创建的后台进程的进程ID。
使用示例:
创建demo3.sh文件,文件内容如下:
#!/bin/bash
echo "输出脚本名称: $0"
echo "输出脚本第一个参数: $1"
echo "输出脚本第二个参数: $2"
echo "输出脚本第三个参数: $3"
echo "当参数超过十个的时候,10以后的参数要用花括号括起来,包括第十个: ${10}"
# 添加后台运行的命令
sleep 10 &
echo "最后执行命令的退出状态: $?"
echo "最后创建的后台进程的进程ID: $!"
四、字符串
常见字符串格式
1.单引号
任何字符串都会原样输出,在字符串中拼接变量是无效的
2.双引号
其中包含了变量,那么该变量会被解析得到的值,而不会原样输出
字符串中还可以出现双引号的子字符串,但需要转意
3.不被引号包围的字符串
不被引号包围的字符串中出现变量也会被解析,这一点和双引号" "包围的字符串一样
字符串中不能出现空格,否则空格后面的内容会被当做其他命令解析
4.获取字符串长度
语法:${#变量名}
字符串拼接
1.无符号拼接
2.双引号拼接
3.混合拼接
字符串截取
语法:
注:字符串下标从0开始
五、数组
数组的定义
语法:
arr1=(item1 item2 item3) #方式一,中间以空格隔开
arr2=([索引1]=item1 [索引2]=item2) #方式二,自定义索引, = 两边不能有空格
数组的获取
1.通过下标获取数组元素,index从0开始
${arr[index]}
2.获取值的同时赋值给其他变量
item=${arr[index]}
3.使用@或*可以获取数组中的所有元素
${arr[@]}
${arr[*]}
4.获取数组长度
${#arr[@]}
${#arr[*]}
5.获取数组指定元素的字符串长度
${#arr[index]}
数组的拼接
数组的删除
1.删除数组中指定的元素
unset arr[index]
2.删除数组所有元素
unset arr
六、内置命令
Shell 内置命令,就是由 Bash shel 自身提供的命令,而不是文件系统中的可执行脚本文件。
使用type 来确定一个命令是否是内置命令:
type 命令
alias设置别名
当某些内置命令过长,而且又经常使用的时候,我们就可以通过设置别名的形式,把复杂的命令设置成简短的命令,语法如下
alias 别名='命令'
在终端运行alias时,可以查看当前的别名列表:
例如我们给ps -aux设置一个别名:
删除某个别名,语法如下:
unalias 别名
删除当前环境下的所有别名,语法如下:
unalias -a
read读取控制台输入
read命令的作用
read 是 Shell 内置命令,用于从标准输入中读取数据并赋值给变量。如果没有进行重定向,默认就是从终端控制台读取用户输入的数据;如果进行了重定向,那么可以从文件中读取数据。
read的语法如下:
read [-options] [var1 var2...]
options表示选项,如下表所示;var表示用来存储数据的变量,可以有一个也可以有多个。
options和var都是可选的,如果没有提供变量名,那么读取的数据将存到环境变量REPLY中。
$REPLY保存read最后一个读入命令的数据
options支持的参数:
使用read给多个变量赋值
创建一个read1.sh文件,内容如下:
#!/bin/bash
#使用read命令读取数据,要有提示信息“请输入姓名、年龄、爱好”,并且将数据赋值给多个变量
read -p "请输入姓名、年龄、爱好:" name age hobby
echo "姓名${name}"
echo "年龄${age}"
echo "爱好${hobby}"
使用read读取一个字符
创建一个read2.sh文件,内容如下:
#!/bin/bash
#使用read命令读取数据,要有提示信息“您确定要删除这条信息吗?请输入(y/n)”
read -n 1 -p "您确定要删除这条信息吗?请输入(y/n)" char
echo "所输入字符为${char}"
使用read限制时间输入
创建一个read3.sh文件,内容如下:
#!/bin/bash
#使用read命令读取数据,要有提示信息"请输入密码(20秒内):",并且设置限制时间20秒
read -t 20 -sp "请输入密码(20秒内):" pwd1
#输出一个换行
echo
#使用read命令读取数据,要有提示信息"请再次输入密码(20秒内):",并且设置限制时间20秒
read -t 20 -sp "请输入密码(20秒内):" pwd2
#输出一个换行
printf "\n"
#校验两次密码是否一致
if [$pwd1==$pwd2]
then
echo "两次密码一致,验证通过"
else
echo "两次密码不一致,验证失败"
fi
exit退出
在 Shell 脚本中,exit
命令用于立即终止脚本的执行。当 exit
命令被执行时,脚本会停止执行后续命令,并返回一个状态值给调用环境(如父 shell 或操作系统)。这个状态值通常用于指示脚本的退出状态或执行结果
exit
命令的基本语法如下:
exit [n]
- 如果没有参数,
exit
将返回状态值 0,这通常表示成功。 - 如果提供了参数
n
,exit
将返回状态值n
。这个值通常是一个介于 1 到 255 之间的整数,用来表示脚本执行失败或异常的情况。
获取脚本状态码:
echo $?
返回非零状态值的意义
在脚本中返回非零状态值是一个重要的最佳实践,特别是当脚本作为更大工作流的一部分时。这允许调用脚本的程序或 shell 能够根据脚本的返回值采取不同的行动,如重新尝试、记录错误或执行清理操作。
示例:编写shell脚本使用exit 退出,退出时返回一个非0数字状态值,执行脚本文件并打印返回状态值:
#!/bin/bash
echo hello
exit 2
declare设置变量属性
declare命令用于声明 shell 变量。可用来声明变量并设置变量的属性,也可用来显示shell函数。若不加上任何参数,则会显示全部的shell变量与函数(与执行set指令的效果相同)。
1.设置变量属性
语法:
declare [+/-][frxiaA][变量名称=设置值]
参数 | 说明 |
---|---|
+/- | "-“可用来指定变量的属性,”+"则是取消变量所设的属性。 |
-f | 仅用显示函数 |
-r | 变量设置成只读 |
-x | 指定变量为环境变量,可以为shell以外的程序来使用 |
-i | [设置值]可以是数值,字符串或运算式。 |
-a | 设置为数组 |
-A | 设置为关联数组(有点像java中的map) |
# 声明一个变量a 为正数变量
declare -i a
a=12 #如果a="aa" 那么打印出来时0
#上面也可以简写为
declare -i a=12
# 如果非要将a进行赋值为"aa"
declare +i a
a="aa" #这样打印出的aa
#也可以设置只读
declare -r a
2.声明关联数组和普通索引数组
新版的bash shell 支持关联数组,关联数组使用字符串作为下标,而不是数字,这样方便我们知道某些内容具体代表什么意义。
关联数组是key-value键值对,有点像是java中的map。
#声明关系数组
declare -A cd
cd["name"]="zhangsan"
cd["age"]=12
#声明索引数组
declare -a cd='([0]="a" [1]="b" [2]="c")' //声明数组变量
let命令
let
是 Bash shell 中的一个内置命令,用于执行算术运算。它主要用于简单的整数运算,如加、减、乘、除以及位运算等。let
命令可以简化在 shell 脚本中进行算术计算的过程,尤其当涉及到变量赋值和表达式计算时。
基本语法
let
的基本语法如下:
let "expression"
或者,
let expression
在第二种形式中,let
和 expression
之间没有引号,这是因为在 let
内部不需要使用引号来包裹表达式。
示例
让我们看一些 let
命令的使用示例:
简单的算术运算
#!/bin/bash
a=5
b=3
let "c=a+b"
echo $c
这段脚本将输出 8
。
变量赋值
let
也可以直接用于变量赋值:
#!/bin/bash
let "result=5+3"
echo $result
这将输出 8
。
位运算
let
还支持位运算:
#!/bin/bash
let "x=5 & 3"
echo $x
这将输出 1
,因为 5
和 3
在二进制下分别是 101
和 011
,按位与的结果是 001
。
自增和自减
let
也支持自增和自减操作:
#!/bin/bash
let "counter=0"
let "counter++"
echo $counter
这将输出 1
。
注意事项
let
默认执行整数运算,不支持浮点数。- 当使用
let
进行赋值时,无需在变量名前添加$
符号。 let
命令的输出不会自动打印,如果需要输出结果,需要通过echo
或其他命令显示地输出。
七、运算符
shell支持多种运算符,包括:
- 算数运算符
- 关系运算符
- 布尔运算符
- 字符串运算符
- 文件测试运算符
原生bash不支持简单的数学运算,但是可以通过其他命令来实现,例如 awk 和 expr,expr 最常用。
算术运算符
下表列出了常用的算术运算符,假定变量 a 为 10,变量 b 为 20:
运算符 | 说明 | 举例 |
---|---|---|
+ | 加法 | `expr $a + $b` 结果为 30。 |
- | 减法 | `expr $a - $b` 结果为 -10。 |
* | 乘法 | `expr $a \* $b` 结果为 200。 |
/ | 除法 | `expr $b / $a` 结果为 2。 |
% | 取余 | `expr $b % $a` 结果为 0。 |
= | 赋值 | a=$b 把变量 b 的值赋给 a。 |
== | 相等。用于比较两个数字,相同则返回 true。 | [ $a == $b ] 返回 false。 |
!= | 不相等。用于比较两个数字,不相同则返回 true。 | [ $a != $b ] 返回 true。 |
注意:
- 条件表达式要放在方括号之间,并且要有空格,例如: [$a==$b] 是错误的,必须写成 [ $a == $b ]。
- 乘号(*)前边必须加反斜杠(\)才能实现乘法运算;
- 在 MAC 中 shell 的 expr 语法是:$((表达式)),此处表达式中的 “*” 不需要转义符号 “\”
示例:
编写expr1.sh脚本文件,内容如下:
#!/bin/bash
a=10
b=20
val=`expr $b % $a`
echo "b % a : $val"
if [ $a == $b ]
then
echo "a 等于 b"
fi
if [ $a != $b ]
then
echo "a 不等于 b"
fi
运行结果如下:
1.扩展
对于算数运算,我们也可以这样的写法:
1.使用[]
#!/bin/bash
num1=10
num2=16
echo "num1+num2="$[num1+num2]
echo "num1-num2="$[num1-num2]
echo "num1*num2="$[num1*num2]
echo "num1/num2="$[num1/num2]
echo "num2/num1="$[num2/num1]
运行结果:
num1+num2=26
num1-num2=-6
num1*num2=160
num1/num2=0
num2/num1=1
注意:做除法运算的时候只显示整数部分,不显示小数部分。
2.使用(())
#!/bin/bash
num1=10
num2=16
echo "num1+num2="$(($num1+$num2))
echo "num1-num2="$(($num1-$num2))
echo "num1*num2="$((num1*num2))
echo "num1/num2="$((num1/num2))
echo "num2/num1="$((num2/num1))
运行结果:
注意:
- 使用(())可以不用$符来获取变量值,它会自动解析变量
- 变量与符号之间可以不用空格
关系运算符
关系运算符只支持数字,不支持字符串,除非字符串的值是数字。
下表列出了常用的关系运算符,假定变量 a 为 10,变量 b 为 20:
运算符 | 说明 | 举例 |
---|---|---|
-eq | 检测两个数是否相等,相等返回 0。 | [ $a -eq $b ] 返回 1。 |
-ne | 检测两个数是否不相等,不相等返回 0。 | [ $a -ne $b ] 返回 0。 |
-gt | 检测左边的数是否大于右边的,如果是,则返回 0。 | [ $a -gt $b ] 返回 1。 |
-lt | 检测左边的数是否小于右边的,如果是,则返回 0。 | [ $a -lt $b ] 返回 0。 |
-ge | 检测左边的数是否大于等于右边的,如果是,则返回 0。 | [ $a -ge $b ] 返回 1。 |
-le | 检测左边的数是否小于等于右边的,如果是,则返回 0。 | [ $a -le $b ] 返回 0。 |
布尔运算符
下表列出了常用的布尔运算符,假定变量 a 为 10,变量 b 为 20:
运算符 | 说明 | 举例 |
---|---|---|
! | 非运算,表达式为 true 则返回 false,否则返回 true。 | [ ! false ] 返回 true。 |
-o | 或运算,有一个表达式为 true 则返回 true。 | [ $a -lt 20 -o $b -gt 100 ] 返回 true。 |
-a | 与运算,两个表达式都为 true 才返回 true。 | [ $a -lt 20 -a $b -gt 100 ] 返回 false。 |
注意:这里的0代表为true,1代表为false
4. 逻辑运算符
以下介绍 Shell 的逻辑运算符,假定变量 a 为 10,变量 b 为 20:
运算符 | 说明 | 举例 |
---|---|---|
&& | 逻辑的 AND | [[ $a -lt 100 && $b -gt 100 ]] 返回 false |
|| | 逻辑的 OR | [[ $a -lt 100 || $b -gt 100 ]] 返回 true |
示例:
#!/bin/bash
a=10
b=20
if [[ $a -lt 100 && $b -gt 100 ]]
then
echo "返回 true"
else
echo "返回 false"
fi
if [[ $a -lt 100 || $b -gt 100 ]]
then
echo "返回 true"
else
echo "返回 false"
fi
执行结果如下:
区别于联系:
[] 与[[ ]] 的区别:
- [[ ]] 中逻辑组合可以使用 && || 符号
- 而[] 里面逻辑组合可以用 -a -o
字符串运算符
下表列出了常用的字符串运算符,假定变量 a 为 “abc”,变量 b 为 “efg”:
运算符 | 说明 | 举例 |
---|---|---|
= | 检测两个字符串是否相等,相等返回 true。 | [ $a = $b ] 返回 false。 |
!= | 检测两个字符串是否不相等,不相等返回 true。 | [ $a != $b ] 返回 true。 |
-z | 检测字符串长度是否为0,为0返回 true。 | [ -z $a ] 返回 false。 |
-n | 检测字符串长度是否不为 0,不为 0 返回 true。 | [ -n “$a” ] 返回 true。 |
$ | 检测字符串是否为空,不为空返回 true。 | [ $a ] 返回 true。 |
注意:这里的0代表为true,1代表为false
文件测试运算符
Shell 中的文件测试运算符允许你在脚本中测试文件的各种属性。这些运算符通常在方括号 [
和 ]
或者 [[
和 ]]
之间使用,并且用于 if 语句或 while 循环中进行条件判断。
在 Linux 系统中,文件类型多种多样,每种类型的文件都有其特定的功能和用途。以下是 Linux 中常见的几种文件类型:
-
普通文件(Regular Files): 这是最常见的文件类型,包含数据、文本、配置信息、程序代码等。在文件系统中表现为一个没有特殊标志的图标或文件名前没有特殊字符。
-
目录文件(Directory Files): 目录也是一种特殊的文件,用于组织其他文件和目录。在命令行中,目录通常以开头的斜杠
/
或点字符.
表示。 -
设备文件(Device Files): 设备文件分为两种:
- 块设备文件(Block Devices):如硬盘驱动器、光盘驱动器等,它们可以随机访问数据。
- 字符设备文件(Character Devices):如串行端口、打印机等,它们提供顺序的数据流。
-
符号链接(Symbolic Links): 又称为软链接,类似于 Windows 中的快捷方式,指向另一个文件或目录的引用。符号链接本身是一个文件,其中包含目标文件的路径。
-
硬链接(Hard Links): 指向同一文件的多个文件名。硬链接直接指向文件的 inode(文件系统中的节点),而不是文件名。删除一个硬链接不会删除文件本身,直到最后一个硬链接被删除,文件才会被删除。
-
套接字文件(Socket Files): 用于进程间通信(IPC),可以是本地通信(Unix Domain Socket)或网络通信(TCP/IP Socket)。
-
管道文件(FIFOs或命名管道): FIFO 是一种特殊的文件,用于进程间通信,它创建了一个数据通道,可以被读取和写入。
-
特殊文件: 包括各种特殊目的的文件,比如
/proc
和/sys
目录下的文件,它们提供了对内核和硬件的访问。
在 Linux 命令行中,可以通过 ls -l
命令查看文件的详细信息,文件类型会显示在最左侧的字符中。例如,-
表示普通文件,d
表示目录,l
表示符号链接,b
表示块设备,c
表示字符设备,p
表示管道文件,s
表示套接字文件。
文件测试运算符用于检测 Unix 文件的各种属性。
属性检测描述如下:
操作符 | 说明 | 举例 |
---|---|---|
-b file | 检测文件是否是块设备文件,如果是,则返回 true。 | [ -b $file ] 返回 false。 |
-c file | 检测文件是否是字符设备文件,如果是,则返回 true。 | [ -c $file ] 返回 false。 |
-d file | 检测文件是否是目录,如果是,则返回 true。 | [ -d $file ] 返回 false。 |
-f file | 检测文件是否是普通文件(既不是目录,也不是设备文件),如果是,则返回 true。 | [ -f $file ] 返回 true。 |
-g file | 检测文件是否设置了 SGID 位,如果是,则返回 true。 | [ -g $file ] 返回 false。 |
-k file | 检测文件是否设置了粘着位(Sticky Bit),如果是,则返回 true。 | [ -k $file ] 返回 false。 |
-p file | 检测文件是否是有名管道,如果是,则返回 true。 | [ -p $file ] 返回 false。 |
-u file | 检测文件是否设置了 SUID 位,如果是,则返回 true。 | [ -u $file ] 返回 false。 |
-r file | 检测文件是否可读,如果是,则返回 true。 | [ -r $file ] 返回 true。 |
-w file | 检测文件是否可写,如果是,则返回 true。 | [ -w $file ] 返回 true。 |
-x file | 检测文件是否可执行,如果是,则返回 true。 | [ -x $file ] 返回 true。 |
-s file | 检测文件是否为空(文件大小是否大于0),不为空返回 true。 | [ -s $file ] 返回 true。 |
-e file | 检测文件(包括目录)是否存在,如果是,则返回 true。 | [ -e $file ] 返回 true |
expr命令详解
`expr` 是一个在 Unix 和类 Unix 系统(如 Linux)中使用的命令行工具,用于执行基本的数学和字符串表达式的解析和计算。`expr` 命令可以处理算术运算、字符串操作以及一些逻辑运算。
算术运算
`expr` 支持以下算术运算:
- 加法:`+`
- 减法:`-`
- 乘法:`*`
- 整除:`/`
- 求余:`%`
例如,计算两个数的和:
expr 5 + 3
字符串操作
`expr` 可以用来进行字符串的比较和截取:
- 比较字符串是否相等:`expr index string1 string2`
- 计算字符串的长度:`expr length string`
- 截取字符串:`expr substr string start end`
例如,获取字符串的长度:
expr length "Hello, world!"
截取字符串的一部分:
expr substr "Hello, world!" 7 6
bc命令详解
Bash shell内置了对整数运算的支持,但是并不支持浮点运算,而 linux bc(basic calculator)命令可以很方便的进行浮点运算.bc命令是Linux简单的计算器,能进行进制转换与计算。能转换的进制包括十六进制、十进制、八进制、二进制等。可以使用的运算符号包括(+)加法、(-)减法、(*)乘法、()除法、(^)指数、(%)余数等。
语法:
bc [options] [参数]
options
- -i:强制进入交互式模式;
- -l:定义使用的标准数学库;
- -w:对POSIX bc的扩展给出警告信息;
- -q:不打印正常的GNU bc环境信息;
- -v:显示指令版本信息;
- -h:显示指令的帮助信息。
示例:
更多内容请参考:05.Shell计算命令:bc命令详解-互动式的数学运算_哔哩哔哩_bilibili
八、流程控制语句
if...else语句
语法:
if condition
then
command1
command2
...
commandN
else
command
fi
if condition1
then
command1
elif condition2
then
command2
else
commandN
fi
if else 的 [...] 判断语句中大于使用 -gt,小于使用 -lt。
if [ "$a" -gt "$b" ]; then
...
fi
如果使用 ((...)) 作为判断语句,大于和小于可以直接使用 > 和 <。
if (( a > b )); then
...
fi
示例:
#!/bin/bash
a=10
b=20
if [ $a == $b ]
then
echo "a 等于 b"
elif (( $a > $b ))
then
echo "a 大于 b"
elif [ $a -lt $b ]
then
echo "a 小于 b"
else
echo "没有符合的条件"
fi
运行结果:
for语句
语法:
for var in item1 item2 ... itemN
do
command1
command2
...
commandN
done
示例:
#!/bin/bash
for loop in 1 2 3 4 5
do
echo "The value is: $loop"
done
运行结果:
while语句
语法:
while condition
do
command
done
示例:
#!/bin/bash
int=1
while(( $int<=5 ))
do
echo $int
let "int++"
done
运行结果:
until 语句
until 循环执行一系列命令直至条件为 true 时停止。
until 循环与 while 循环在处理方式上刚好相反。
一般 while 循环优于 until 循环,但在某些时候—也只是极少数情况下,until 循环更加有用。
until 语法格式:
until condition
do
command
done
condition 一般为条件表达式,如果返回值为 false,则继续执行循环体内的语句,否则跳出循环。
以下实例我们使用 until 命令来输出 0 ~ 9 的数字:
#!/bin/bash
int=1
while(( $int<=5 ))
do
echo $int
let "int++"
done
运行结果:
case ... esac
case ... esac 为多选择语句,与其他语言中的 switch ... case 语句类似,是一种多分支选择结构,每个 case 分支用右圆括号开始,用两个分号 ;; 表示 break,即执行结束,跳出整个 case ... esac 语句,esac(就是 case 反过来)作为结束标记。
可以用 case 语句匹配一个值与一个模式,如果匹配成功,执行相匹配的命令。
case ... esac 语法格式如下:
case 值 in
模式1)
command1
command2
...
commandN
;;
模式2)
command1
command2
...
commandN
;;
esac
case 工作方式如上所示,取值后面必须为单词 in,每一模式必须以右括号结束。取值可以为变量或常数,匹配发现取值符合某一模式后,其间所有命令开始执行直至 ;;。
取值将检测匹配的每一个模式。一旦模式匹配,则执行完匹配模式相应命令后不再继续其他模式。如果无一匹配模式,使用星号 * 捕获该值,再执行后面的命令。
下面的脚本提示输入 1 到 4,与每一种模式进行匹配:
#!/bin/bash
echo '输入 1 到 4 之间的数字:'
echo '你输入的数字为:'
read aNum
case $aNum in
1) echo '你选择了 1'
;;
2) echo '你选择了 2'
;;
3) echo '你选择了 3'
;;
4) echo '你选择了 4'
;;
*) echo '你没有输入 1 到 4 之间的数字'
;;
esac
运行结果:
跳出循环
在循环过程中,有时候需要在未达到循环结束条件时强制跳出循环,Shell 使用两个命令来实现该功能:break 和 continue。
1.break 命令
break 命令允许跳出所有循环(终止执行后面的所有循环)。
下面的例子中,脚本进入死循环直至用户输入数字大于5。要跳出这个循环,返回到shell提示符下,需要使用break命令。
#!/bin/bash
while :
do
echo -n "输入 1 到 5 之间的数字:"
read aNum
case $aNum in
1|2|3|4|5) echo "你输入的数字为 $aNum!"
;;
*) echo "你输入的数字不是 1 到 5 之间的! 游戏结束"
break
;;
esac
done
2.continue
continue 命令与 break 命令类似,只有一点差别,它不会跳出所有循环,仅仅跳出当前循环。
对上面的例子进行修改:
#!/bin/bash
while :
do
echo -n "输入 1 到 5 之间的数字: "
read aNum
case $aNum in
1|2|3|4|5) echo "你输入的数字为 $aNum!"
;;
*) echo "你输入的数字不是 1 到 5 之间的!"
continue
echo "游戏结束"
;;
esac
done
select语句
在 Bash shell 脚本中,select
命令提供了一种简单的菜单选择机制,允许用户从一组选项中做出选择。这对于创建交互式的脚本非常有用,可以用于构建命令行界面(CLI)应用或菜单驱动的脚本。
语法:
select NAME in LIST; do COMMANDS; done
示例:
#!/bin/bash
options=("Option 1" "Option 2" "Exit")
select opt in "${options[@]}"; do
case $opt in
"Option 1")
echo "You chose option 1."
;;
"Option 2")
echo "You chose option 2."
;;
"Exit")
break
;;
*) echo "Invalid option. Please select again." ;;
esac
done
运行结果:
九、函数
自定义函数
语法:
[ function ] funname [()]
{
action;
[return int;]
}
说明:
- 1、可以带 function fun() 定义,也可以直接 fun() 定义,不带任何参数。
- 2、参数返回,可以显示加:return 返回,如果不加,将以最后一条命令运行结果,作为返回值。 return 后跟数值 n(0-255).
下面的例子定义了一个函数并进行调用:
#!/bin/bash
demoFun(){
echo "Hello World!"
}
echo "-----函数开始执行-----"
demoFun
echo "-----函数执行完毕-----"
运行结果:
下面定义一个带有 return 语句的函数:
#!/bin/bash
funWithReturn(){
echo "这个函数会对输入的两个数字进行相加运算..."
echo "输入第一个数字: "
read aNum
echo "输入第二个数字: "
read anotherNum
echo "两个数字分别为 $aNum 和 $anotherNum !"
return $(($aNum+$anotherNum))
}
funWithReturn
echo "输入的两个数字之和为 $? !"
运行结果:
函数返回值在调用该函数后通过 $? 来获得。
注意:所有函数在使用前必须定义。这意味着必须将函数放在脚本开始部分,直至shell解释器首次发现它时,才可以使用。调用函数仅使用其函数名即可。
注意: return 语句只能返回一个介于 0 到 255 之间的整数,而两个输入数字的和可能超过这个范围。
要解决这个问题,您可以修改 return 语句,直接使用 echo 输出和而不是使用 return:
funWithReturn(){
echo "这个函数会对输入的两个数字进行相加运算..."
echo "输入第一个数字: "
read aNum
echo "输入第二个数字: "
read anotherNum
sum=$(($aNum + $anotherNum))
echo "两个数字分别为 $aNum 和 $anotherNum !"
echo $sum # 输出两个数字的和
}
在Shell中,调用函数时可以向其传递参数。在函数体内部,通过 $n 的形式来获取参数的值,例如,$1表示第一个参数,$2表示第二个参数...,当参数超过10个,获取的参数的方式为${10},${11}...
带参数的函数示例:
#!/bin/bash
funWithParam(){
echo "第一个参数为 $1 !"
echo "第二个参数为 $2 !"
echo "第十个参数为 $10 !"
echo "第十个参数为 ${10} !"
echo "第十一个参数为 ${11} !"
echo "参数总数有 $# 个!"
echo "作为一个字符串输出所有参数 $* !"
}
funWithParam 1 2 3 4 5 6 7 8 9 34 73
运行结果:
十、输入/输出重定向
输入输出重定向是 Unix/Linux shell 中一个非常强大的功能,它允许你改变命令的输入源或输出目的地,从而实现对数据流的控制。输入输出重定向可以让你避免不必要的屏幕输出,将数据保存到文件,或将数据从文件读入命令,甚至在多个命令之间传递数据。
重定向命令列表如下:
命令 | 说明 |
---|---|
command > file | 将输出重定向到 file。 |
command < file | 将输入重定向到 file。 |
command >> file | 将输出以追加的方式重定向到 file。 |
n > file | 将文件描述符为 n 的文件重定向到 file。 |
n >> file | 将文件描述符为 n 的文件以追加的方式重定向到 file。 |
n >& m | 将输出文件 m 和 n 合并。 |
n <& m | 将输入文件 m 和 n 合并。 |
<< tag | 将开始标记 tag 和结束标记 tag 之间的内容作为输入。 |
输出重定向
重定向一般通过在命令间插入特定的符号来实现。特别的,这些符号的语法如下所示:
command1 > file1
上面这个命令执行command1然后将输出的内容存入file1。
注意任何file1内的已经存在的内容将被新内容替代。如果要将新内容添加在文件末尾,请使用>>操作符。
示例:
重定向输入
我们先来学习一下wc命令,Linux的wc命令可以用来统计文件的字节个数、行数、单词数
语法:
wc [options] [文件名]
options选项如下:
在了解上述命令后,我们继续学习重定向输入:
一般情况下,每个 Unix/Linux 命令运行时都会打开三个文件:
- 标准输入文件(stdin):stdin的文件描述符为0,Unix程序默认从stdin读取数据。
- 标准输出文件(stdout):stdout 的文件描述符为1,Unix程序默认向stdout输出数据。
- 标准错误文件(stderr):stderr的文件描述符为2,Unix程序会向stderr流中写入错误信息。
默认情况下,command > file 将 stdout 重定向到 file,command < file 将stdin 重定向到 file。
如果希望 stderr 重定向到 file,可以这样写:
command 2>file
如果希望 stderr 追加到 file 文件末尾,可以这样写:
command 2>>file
2 表示标准错误文件(stderr)。
如果希望将 stdout 和 stderr 合并后重定向到 file,可以这样写:
command >> file 2>&1
如果希望对 stdin 和 stdout 都重定向,可以这样写:
command < file1 >file2
command 命令将 stdin 重定向到 file1,将 stdout 重定向到 file2。
示例:
参考文章:Shell 教程 | 菜鸟教程 (runoob.com)