从 0 开始学 Linux:Bash Shell 脚本入门
Bash 是一个支持脚本的命令行解释器,你可以利用脚本来自动化执行一些重复性的任务。
本文将在已有的基础上,学习 Bash Shell 脚本的基本语法和使用方法。若你对 Bash Shell 还不熟悉,请先阅读以下文章:
从 0 开始学 Linux:Bash Shell 快速入门脚本文件
脚本文件以 .sh 结尾,并包含一系列命令。
若要运行脚本,需为脚本文件添加可执行权限并执行,也可以通过 bash 命令以执行。
1 | chmod +x <脚本文件路径> |
1 | bash <脚本文件路径> |
定义解释器
脚本文件第一行必须指定脚本的解释器,即 /bin/bash。
1 |
当然,你也可以指定其它的 Shell 解释器,如 /bin/sh、/bin/zsh等。甚至,你还可以使用 Python 解释器以执行 Python 脚本。
1 |
注释
注释以 # 开头,表示后面的内容为注释。
1 | # 这是一行注释 |
变量
变量是存储数据的容器,可以用来保存字符串、数字、列表等数据。
定义变量
变量名只能包含字母、数字和下划线,且不能以数字开头。
你可以利用 ` … ` 来包裹命令,或者用 $(command) 定义变量。其中的 command 为执行的命令,将输出结果赋值给变量。
1 | # 定义变量 |
利用用户输入赋值
你可以利用 read 命令从用户输入中获取值并赋值给变量。
1 | # 利用 read 命令获取用户输入并赋值给变量 |
-p 参数表示提示用户输入,name 为用户所赋值的变量。
特殊变量
在 Bash 中,有一些特殊的变量,可以用来获取系统信息等,大致如下:
$0: 当前脚本的文件名。$n: 传递给脚本或函数的参数。其中,n需要代替为对应的参数序号。$#: 传递给脚本或函数的参数个数。$*: 传递给脚本或函数的所有参数。$@: 传递给脚本或函数的所有参数,每个参数以空格分隔。$?: 上个命令的退出状态。0表示命令成功,否则表示失败。$$: 当前 Shell 进程的进程 ID。$!: 当前 Shell 最后运行的后台进程的进程 ID。$HOME: 当前用户的主目录。$PWD: 当前工作目录。$OLDPWD: 上一个工作目录。$UID: 当前用户的 UID。$EUID: 当前用户的有效 UID。$USER: 当前用户的用户名。$GROUPS: 当前用户的组列表。$PATH: 查找命令的路径。
运算变量
变量还可以用来执行简单的运算。
你可以利用 expr 命令进行基本的运算,也可以利用 $((...)) 或 $[...] 进行更复杂的运算。
1 | # 定义变量 |
注意:
使用 * 运算符时,需要使用反转义符 \ 来转义。即 \* 而不是 *。
条件语句
条件语句可以根据条件执行不同的代码块。
语句结构
1 | # if 语句 |
运算符
条件语句中可以使用以下运算符:
-eq:等于equals。-ne:不等于not equal。-gt:大于greater than。-lt:小于less than。-ge:大于等于greater than or equal。-le:小于等于less than or equal。
这里假设 x 和 y 分别等于 10 和 20,则:
| 示例 | 结果 |
|---|---|
[ $x -eq $y ] |
false |
[ $x -ne $y ] |
true |
[ $x -gt $y ] |
false |
[ $x -lt $y ] |
true |
[ $x -ge $y ] |
false |
[ $x -le $y ] |
true |
注意:
这里的 -eq 等运算符前后都需要有空格。且 -eq 等运算符只能用于数字比较,不能用于字符串比较。
字符串比较
条件语句也可以比较字符串。通常,字符串比较使用 == 、 !=、=~ 等运算符。
-
字符串相等关系可以使用
==运算符,表示任意字符串相等关系。 -
字符串包含关系可以使用
=~或者*string*运算符,表示任意字符串包含关系。 -
字符串不匹配关系可以使用
!=运算符,表示任意字符串不匹配关系。 -
字符串不包含关系可以使用
!=运算符和*运算符,表示任意字符串不包含关系。
1 | # 定义变量 |
逻辑运算符
条件语句还可以使用逻辑运算符 && 和 || 来组合多个条件。
&&: 逻辑与and。||: 逻辑或or。
示例:判断 var1 和 var2 是否都在 vars 列表中, var2 或 var3 两者之中是否有一元素在 vars 列表中。
1 | # 定义变量 |
示例
示例 1:判断 ~/apt/history.log 文件是否存在,若不存在,则复制 /var/log/apt/history.log 文件到 ~/apt/history.log 中。
注意:你还需要判断 ~/apt 目录是否存在。
1 | # 判断 ~/apt 目录是否存在 |
示例 2:判断当前用户是否为 root,若不是,则提示用户输入密码。
1 |
|
循环语句
循环语句可以重复执行代码块。
语句结构
在使用 for 循环时,变量的取值可以是列表、范围或命令的输出结果。
其中的 <命令> 可以用反引号 ` … ` 包裹,也可以用 $() 包裹。
1 | # for 循环 |
循环控制
循环语句还可以控制循环的次数。
break: 跳出循环。continue: 跳过当前循环,继续下一次循环。
示例
示例 1:打印 1 到 10 的偶数。当遇到 6 时,跳出循环。
1 | # for 循环 |
若你对 Java 熟悉,你可能还会发现 for 循环的语法类似于 Java 中的 for 循环。
1 | # for 循环 |
示例 2:打印 1 到 10 的所有偶数,当遇到 6 时,跳过当前循环,继续下一次循环。
1 | # while 循环 |
示例 3:打印 1 到 10 的所有偶数,当遇到 4 时,跳过当前循环;当遇到 6 时,跳出循环。
1 | # until 循环 |
选择语句
选择语句可以根据用户的选择执行不同的代码块。
语句结构
select 语句可以让用户从列表、范围、命令输出结果中选择一个值,并赋值给变量。
1 | # select 语句 |
case 语句也可以根据变量的值执行不同的代码块。使用 case 语句时需要注意以下几点:
case语句必须与esac配对使用。case语句中的in必须与)配对使用。case语句中的;;必须与)配对使用。case语句中的*)表示其他情况。
1 | case <变量> in |
注意:
选择语句只能在交互式 Shell 中使用,如 bash 或 zsh。
注意每条命令的结尾必须以 ;; 结尾,表示选择结束。
示例
示例 1:提示用户输入数字,并根据输入执行不同的操作。
- 输入
start时启动服务器; - 输入
stop时停止服务器; - 输入
restart时重启服务器; - 输入
exit时退出脚本。 - 输入其他内容时显示错误信息。
1 | # select 语句 |
注意:
当执行 select 语句时,脚本会持续循环,直到用户输入 exit 选项才能退出循环。
若用户需要直接退出程序,按下 Ctrl+C 即可。
示例 2:提示用户输入数字,并根据输入执行不同的操作。
- 输入
1时,打印You entered 1。 - 输入
2时,打印You entered 2。 - 输入
3时,打印You entered 3。 - 输入其他值时,打印
Invalid input。
1 | # case 语句 |
函数
函数可以将一系列命令封装成一个整体,可以重复使用。
语法结构
1 | # 定义函数 |
注意: 关于函数定义,你需要注意以下几点:
-
函数定义时,函数名只能包含字母、数字和下划线,且不能以数字开头。
-
函数调用时,函数名后面可以加上参数,参数之间用空格分隔。
-
函数定义时,函数体必须用花括号
{}包裹。 -
函数定义时,函数体内的变量作用域为局部变量,函数执行结束后,局部变量会被销毁。
-
函数可以返回值,使用
return语句。但必须将return语句置于函数体最后一行。否则,函数将立即结束。 -
函数可以调用其他函数。
示例
示例 1:定义一个函数 hello(),要求用户输入姓名,并打印 Hello, <姓名>!。
1 | # 定义函数 |
示例 2:定义一个函数 times() 和一个函数 sum(),要求用户输入一个数字,并打印 The sum is <结果>。
参考输入输出:
3-->The sum is 65-->The sum is 12010-->The sum is 3628800
1 | # 定义函数 |
示例 3:定义一个函数 install_packages(),要求用户输入软件包名,并安装指定的软件包。定义一个函数 package_manager(),用于搜寻系统中可用的软件包管理工具,并安装指定的软件包。
注意:针对 Arch Linux 使用的 pacman 的命令有所不同,需要进行单独修改。
1 | # 定义函数 |
- 标题: 从 0 开始学 Linux:Bash Shell 脚本入门
- 作者: CatIsNotFound
- 创建于 : 2024-06-09 13:15:33
- 更新于 : 2024-10-19 22:59:35
- 链接: https://catisnotfound.github.io/2024/06/从-0-开始学-Linux-Bash-Shell-脚本入门/
- 版权声明: 本文章采用 CC BY-NC-SA 4.0 进行许可。