Shell 编程基础知识总结
Shell 编程在我们的日常开发工作中非常实用,目前 Linux 系统下最流行的运维自动化语言就是 Shell 和 Python 了。
一、走进 Shell 编程的大门
什么是 Shell?
Shell 是一个命令行界面(CLI),它为用户提供了与操作系统交互的方式。在 Linux 和类 Unix 系统中,Shell 是用户和操作系统之间的中介,通过它,用户可以执行命令、管理文件、运行程序、控制进程等。
1. Shell 的作用
- 命令解释器:Shell 是一个命令解释器,用户输入的命令会被 Shell 解释并执行。它接收用户的输入,然后通过系统调用执行相应的任务。
- 脚本编程:除了执行单个命令外,Shell 还支持脚本编程(Shell 编程)。你可以将一系列命令编写成脚本文件,自动化执行某些操作。这样,可以将常见任务进行封装,并在需要时重复执行。
2. Shell 编程
- 命令逻辑化:Shell 编程是通过编写一系列的 Linux 命令来完成自动化任务。通过对一堆命令的逻辑化处理,Shell 编程可以帮助用户提高效率,减少手动操作。
- 自动化任务:Shell 编程常常用于自动化任务,例如备份文件、监控系统状态、批量处理文件等。
3. Shell 的常见类型
- Bash:最常用的 Shell,几乎所有 Linux 发行版都默认使用 Bash(Bourne Again Shell)作为默认的 Shell。
- Zsh:一种功能丰富的 Shell,具有许多改进和扩展功能,特别适合开发人员。
- Fish:一种用户友好的 Shell,拥有自动补全、语法高亮等特性,适合新手。
- Tcsh:是 C Shell 的一种扩展,具有类似 C 语言的语法。
总结
Shell 是用户与操作系统进行交互的工具,它不仅可以用来执行简单的命令,还可以通过 Shell 编程来自动化任务、提高工作效率。学习和掌握 Shell 编程能够帮助开发人员、运维人员更高效地管理和操作 Linux 系统。
为什么要学 Shell?
学 Shell 编程对于后端开发人员来说,具有很高的实用性和工作效率提升的作用。许多人可能认为 Shell 编程是运维工作的一部分,主要由运维人员来负责,然而这种观点并不准确。Shell 编程对于开发人员同样重要,尤其在以下几个方面:
1. 提高工作效率
- 自动化任务:Shell 编程可以让你通过脚本自动化许多重复性任务,例如部署、测试、日志分析等。这种自动化不仅减少了手动操作的错误,还显著提高了工作效率。
- 快速执行命令:作为 Linux 系统中的默认命令行工具,Shell 让你能够高效地与操作系统交互,执行文件管理、网络配置、进程控制等任务。
2. 常见应用场景
- 服务监控和管理:Shell 在服务启动、停止和重启时非常常用,特别是在一些大型应用的运维中。
- 数据备份与恢复:Shell 可以编写脚本定期自动备份数据库、文件系统等数据,保证数据的安全性。
- 日志分析:Shell 脚本可以用来定期分析日志文件,发现潜在的问题,并发出预警或自动处理。
- 批量操作:Shell 非常适合处理批量的文件操作、系统监控等任务,特别是在多台服务器的管理中,可以通过编写脚本进行批量处理。
3. 与 Python 的对比
- Shell vs. Python:虽然 Python 可以处理复杂的运维逻辑和开发更复杂的工具,但 Shell 编程更适合用于日常的命令执行、任务自动化和简单的系统脚本。Python 更侧重于处理复杂的逻辑和系统开发。
- Shell 是必备的技能:在 Linux 系统中,Shell 是基础工具。无论是开发、运维还是管理,Shell 的运用都非常广泛,掌握 Shell 可以帮助你更高效地操作系统,快速执行脚本。
4. 互联网公司对 Shell 编程的要求
很多知名互联网公司在招聘后端开发人员时,都将 Shell 编程作为必备技能之一。Shell 编程能力帮助开发人员在日常工作中处理服务器管理、自动化部署等任务,提高团队工作效率和产品稳定性。
总结
尽管 Shell 编程与开发工作看似不直接相关,但它在提高工作效率、自动化运维、管理系统等方面有着不可替代的作用。学习 Shell 编程不仅是后端开发人员的基本能力,也是增强职场竞争力的重要手段。
Shell 编程的 Hello World
这是一个经典的“Hello World”程序,可以帮助我们快速了解如何编写和执行 Shell 脚本。
步骤
创建脚本文件:
通过touch
命令创建一个名为helloworld.sh
的空文件:touch helloworld.sh
脚本文件的扩展名通常使用
.sh
,不过这并不影响脚本的执行。赋予执行权限:
使用chmod
命令赋予脚本执行权限:chmod +x helloworld.sh
这样就可以运行该脚本。
编辑脚本文件:
使用vim
或其他文本编辑器打开文件并编辑:vim helloworld.sh
在编辑模式下输入以下内容:
#!/bin/bash # 第一个shell小程序,echo 是 linux 中的输出命令。 echo "helloworld!"
#!/bin/bash
是告诉系统使用哪种 Shell 来执行该脚本。echo
是 Shell 中用于输出的命令,它会打印出后面的字符串。
运行脚本:
使用以下命令运行脚本:./helloworld.sh
./
表示当前目录。由于当前目录通常不在PATH
中,所以需要加上./
来告诉系统从当前目录中执行脚本。
输出:
当运行脚本时,终端会输出:
helloworld!
总结:
这就是一个简单的 Shell 脚本,它演示了如何创建脚本、赋予执行权限、编辑脚本内容并最终运行脚本。掌握这些基础操作后,你可以逐步扩展脚本功能,实现更多自动化任务。
二、Shell 变量
Shell 编程中的变量介绍
在 Shell 编程中,变量用于存储值,这些值可以是字符串、数字或系统信息等。Shell 中的变量大体可以分为三类:
1. 自定义变量
自定义变量是用户在脚本中自行定义的变量,这些变量仅在当前 Shell 实例中有效,其他 Shell 启动的程序不能访问它们。
#!/bin/bash
# 自定义变量 hello
hello="hello world"
echo $hello
hello="hello world"
:定义了一个名为hello
的变量,并赋值为"hello world"
。echo $hello
:输出变量hello
的值。
2. Linux 已定义的环境变量
环境变量是操作系统定义并提供的变量,这些变量在系统中是全局的,所有进程都可以访问它们。常见的环境变量包括 PATH
, HOME
, SHELL
等。
常见环境变量:
- PATH:指定了 shell 查找命令的目录。
- HOME:当前用户的主目录。
- HISTSIZE:历史命令的数量。
- SHELL:当前用户的 Shell 类型。
使用环境变量:
echo $HOME # 输出当前用户的主目录
echo $SHELL # 输出当前 Shell 类型
3. Shell 变量
Shell 变量是由 Shell 自身定义和管理的特殊变量。Shell 变量中有一部分是环境变量,有一部分是局部变量。
变量命名的注意事项:
- 变量名只能包含英文字母(大小写)、数字和下划线。
- 变量名不能以数字开头,但可以以下划线
_
开头。 - 变量名中不能包含空格。
- 变量名不能使用 Shell 中的保留关键字(例如
if
,while
,for
等)。
总结:
在 Shell 编程中,我们可以利用自定义变量、环境变量以及 Shell 变量来实现不同的功能。变量的命名应遵循一定的规则,以确保脚本的正确性和可维护性。
Shell 字符串入门
在 Shell 编程中,字符串是最常用的数据类型。与 Java 等其他语言不同,Shell 对字符串的处理有些独特的规则,特别是在单引号和双引号的使用上。
单引号字符串
在 Shell 中,单引号中的内容会被原样输出,不会对其中的特殊字符(如 $
、反引号等)进行替换或扩展。因此,$name
会被当做普通字符串处理,而不会被解释为变量。
#!/bin/bash
name='SnailClimb'
hello='Hello, I am $name!'
echo $hello
输出:
Hello, I am $name!
双引号字符串
而双引号中的内容允许变量替换和命令替换等特殊字符进行处理。在双引号中,$name
会被解释为变量,且其值会被展开。
#!/bin/bash
name='SnailClimb'
hello="Hello, I am $name!"
echo $hello
输出:
Hello, I am SnailClimb!
总结:
- 单引号:字符串中的任何特殊字符(如
$
、反引号等)都不会被处理,按字面意义输出。 - 双引号:支持变量替换、命令替换等特殊字符的处理。
Shell 字符串常见操作
在 Shell 编程中,字符串操作非常常见,以下是一些常用的字符串操作示例。
拼接字符串
在 Shell 中拼接字符串可以使用双引号和单引号,注意不同的拼接方式可能会影响变量替换。
#!/bin/bash
name="SnailClimb"
# 使用双引号拼接
greeting="hello, "$name" !"
greeting_1="hello, ${name} !"
echo $greeting $greeting_1
# 使用单引号拼接
greeting_2='hello, '$name' !'
greeting_3='hello, ${name} !'
echo $greeting_2 $greeting_3
输出结果:
hello, SnailClimb ! hello, SnailClimb !
hello, SnailClimb ! hello, ${name} !
获取字符串长度
获取字符串的长度可以使用 ${#string}
或 expr length
命令。
#!/bin/bash
# 获取字符串长度
name="SnailClimb"
# 第一种方式
echo ${#name} # 输出 10
# 第二种方式
expr length "$name"; # 输出 10
输出结果:
10
10
注意:在使用 expr
时,运算符两边必须有空格,否则会输出错误的结果:
expr 5+6 # 直接输出 5+6
expr 5 + 6 # 输出 11
对于某些运算符(如乘法),需要使用反斜杠转义:
expr 5 * 6 # 输出错误
expr 5 \* 6 # 输出 30
截取子字符串
可以使用 ${string:start:length}
的方式来截取子字符串,也可以使用 expr
来根据模式匹配截取。
简单的字符串截取:
# 从字符串第 1 个字符开始,往后截取 10 个字符
str="SnailClimb is a great man"
echo ${str:0:10} # 输出: SnailClimb
根据表达式截取:
#!/bin/bash
var="https://www.runoob.com/linux/linux-shell-variable.html"
# % 表示删除从后匹配,最短匹配
# %% 表示删除从后匹配,最长匹配
# # 表示删除从头匹配,最短匹配
# ## 表示删除从头匹配,最长匹配
s1=${var%%t*} # 输出: https
s2=${var%t*} # 输出: https://www.runoob.com/linux/linux-shell-variable.h
s3=${var%%.*} # 输出: https://www
s4=${var#*/} # 输出: /www.runoob.com/linux/linux-shell-variable.html
s5=${var##*/} # 输出: linux-shell-variable.html
总结:
- 拼接字符串:可以通过双引号和单引号拼接。双引号支持变量替换,而单引号则不会。
- 获取字符串长度:可以使用
${#string}
或expr length "$string"
。 - 截取子字符串:可以使用
${string:start:length}
,也可以使用模式匹配删除部分字符串。
Shell 数组
Bash 支持一维数组(不支持多维数组),并且数组的大小不受限制。下面是一些常见的数组操作示例,包括如何创建数组、获取数组长度、访问或删除特定位置的元素、删除整个数组以及遍历数组。
创建数组和获取数组长度
#!/bin/bash
array=(1 2 3 4 5)
# 获取数组长度
length=${#array[@]} # 使用 @ 或 * 获取数组长度
length2=${#array[*]} # 使用 * 获取数组长度
echo $length # 输出:5
echo $length2 # 输出:5
访问数组元素
数组是从索引 0 开始的,因此可以通过索引访问特定的数组元素。
# 输出数组第三个元素(索引从 0 开始,所以是第 3 个元素)
echo ${array[2]} # 输出:3
删除特定元素
使用 unset
命令可以删除数组中特定位置的元素。
unset array[1] # 删除下标为 1 的元素(也就是删除第二个元素)
删除元素后,数组的其他元素会向前移动,索引会重新排列。
遍历数组
可以使用 for
循环来遍历数组并输出每个元素。
# 遍历数组
for i in ${array[@]}; do
echo $i
done
# 输出:
# 1
# 3
# 4
# 5
删除整个数组
使用 unset
删除整个数组时,数组中的所有元素都会被移除。
unset array # 删除整个数组
# 遍历已删除的数组,数组为空,不会输出任何内容
for i in ${array[@]}; do
echo $i
done
# 无输出
总结
- 创建数组:通过括号
( )
创建数组,元素之间用空格分隔。 - 获取数组长度:使用
${#array[@]}
或${#array[*]}
来获取数组长度。 - 访问数组元素:通过
${array[index]}
来访问指定索引的元素。 - 删除数组元素:使用
unset array[index]
来删除特定元素。 - 遍历数组:使用
for
循环和${array[@]}
或${array[*]}
来遍历数组元素。 - 删除整个数组:使用
unset array
来删除整个数组。
这些基础操作可以帮助你有效地管理和使用数组。
三、Shell 基本运算符
Shell 编程支持下面几种运算符
- 算数运算符
- 关系运算符
- 布尔运算符
- 字符串运算符
- 文件测试运算符
算数运算符
在 Shell 编程中,算数运算符用于执行基本的数学运算。常见的算数运算符如下:
运算符 | 说明 | 示例 |
---|---|---|
+ | 加法 | expr $a + $b |
- | 减法 | expr $a - $b |
* | 乘法 | expr $a \* $b |
/ | 除法 | expr $a / $b |
% | 取余 | expr $a % $b |
= | 赋值 | a=3 |
注意: 在 Shell 中,乘法 *
运算符前需要加反斜杠 \
,否则会被解释为通配符。
示例:加法运算
#!/bin/bash
a=3
b=3
val=`expr $a + $b` # 使用反引号执行加法运算
echo "Total value : $val" # 输出:Total value : 6
在这个示例中,我们使用 expr
命令来执行加法运算。需要注意的是,expr
命令使用反引号(`
)来执行运算。
示例:其他算数运算
#!/bin/bash
a=10
b=5
# 加法
sum=`expr $a + $b`
echo "Sum: $sum" # 输出:Sum: 15
# 减法
diff=`expr $a - $b`
echo "Difference: $diff" # 输出:Difference: 5
# 乘法
prod=`expr $a \* $b`
echo "Product: $prod" # 输出:Product: 50
# 除法
quot=`expr $a / $b`
echo "Quotient: $quot" # 输出:Quotient: 2
# 取余
rem=`expr $a % $b`
echo "Remainder: $rem" # 输出:Remainder: 0
总结
- 使用
expr
命令进行基本算数运算。 - 乘法
*
需要加反斜杠\
,以防止被解释为通配符。 - 运算符之间的操作数应当有空格分隔。
关系运算符
在 Shell 中,关系运算符用于比较两个整数的大小。它们只支持数字,且无法直接用于字符串比较(除非字符串的值是数字)。常用的关系运算符如下:
运算符 | 说明 | 示例 |
---|---|---|
-eq | 等于 | if [ $a -eq $b ] |
-ne | 不等于 | if [ $a -ne $b ] |
-gt | 大于 | if [ $a -gt $b ] |
-ge | 大于等于 | if [ $a -ge $b ] |
-lt | 小于 | if [ $a -lt $b ] |
-le | 小于等于 | if [ $a -le $b ] |
示例:关系运算符判断
#!/bin/bash
score=90
maxscore=100
if [ $score -eq $maxscore ]
then
echo "A"
else
echo "B"
fi
在这个示例中,脚本判断 score
是否等于 maxscore
,如果相等则输出 A
,否则输出 B
。
输出结果:
B
这是因为 score
的值是 90,而 maxscore
的值是 100,因此 90 -eq 100
为 false
,输出 B
。
示例:其他关系运算符
#!/bin/bash
a=10
b=20
# 等于
if [ $a -eq $b ]; then
echo "$a is equal to $b"
else
echo "$a is not equal to $b"
fi
# 大于
if [ $a -gt $b ]; then
echo "$a is greater than $b"
else
echo "$a is not greater than $b"
fi
# 小于等于
if [ $a -le $b ]; then
echo "$a is less than or equal to $b"
else
echo "$a is greater than $b"
fi
输出结果:
10 is not equal to 20
10 is not greater than 20
10 is less than or equal to 20
总结
- 关系运算符只适用于整数,字符串比较要使用
=
或!=
。 -eq
、-ne
、-gt
等用于比较整数的关系。- 关系运算符适用于
if
语句来进行条件判断。
逻辑运算符
逻辑运算符用于处理布尔逻辑,Shell 中常用的逻辑运算符有:
| 运算符 | 说明 | 示例 |
| ------ | ------ | --------------------------------- | ------ | ---------------- | --- | ------------- |
| &&
| 逻辑与 | if [ $a -eq 1 ] && [ $b -eq 2 ]
|
| | |
| 逻辑或 | if [ $a -eq 1 ] | | [ $b -eq 2 ]
|
| !
| 逻辑非 | if [ ! -e "$file" ]
|
示例:逻辑与运算符
#!/bin/bash
a=$(( 1 && 0 )) # 逻辑与运算,只有两边都是1时结果才是1,否则是0
echo $a # 输出 0
说明:
- 逻辑与运算符 (
&&
) 用于判断两个条件是否同时为真。只有在两个条件都为真时,结果才为真。 - 这里
1 && 0
的结果是0
,因为只有在两个操作数都为1
时才会返回1
。
示例:逻辑或运算符
#!/bin/bash
a=$(( 1 || 0 )) # 逻辑或运算,只有两边都为0时结果才是0,否则为1
echo $a # 输出 1
说明:
- 逻辑或运算符 (
||
) 用于判断两个条件是否有一个为真。只要其中一个条件为真,结果就是真。 - 这里
1 || 0
的结果是1
,因为1
为真,结果即为真。
示例:逻辑非运算符
#!/bin/bash
a=5
if [ ! $a -eq 0 ]; then
echo "$a is not 0" # 输出: 5 is not 0
fi
说明:
- 逻辑非运算符 (
!
) 用于取反。它反转条件判断的结果。 - 如果
a
不是 0,!
运算符将其取反,结果变为真。
总结
&&
逻辑与运算符:只有左右两边都为真时,结果为真。||
逻辑或运算符:只要左右两边有一个为真,结果为真。!
逻辑非运算符:用于反转条件结果。
布尔运算符
布尔运算符用于处理逻辑条件的运算,在 Shell 脚本中常用的布尔运算符有以下几种:
运算符 | 说明 | 示例 |
---|---|---|
-o | 逻辑或(OR) | if [ $a -eq 1 -o $b -eq 2 ] |
-a | 逻辑与(AND) | if [ $a -eq 1 -a $b -eq 2 ] |
! | 逻辑非(NOT) | if [ ! -e "$file" ] |
布尔运算符示例
逻辑或运算符 -o
#!/bin/bash
a=1
b=2
if [ $a -eq 1 -o $b -eq 3 ]; then
echo "One condition is true"
fi
# 输出:One condition is true
逻辑与运算符 -a
#!/bin/bash
a=1
b=2
if [ $a -eq 1 -a $b -eq 2 ]; then
echo "Both conditions are true"
fi
# 输出:Both conditions are true
逻辑非运算符 !
#!/bin/bash
a=5
if [ ! $a -eq 0 ]; then
echo "$a is not 0"
fi
# 输出:5 is not 0
总结
-o
:表示逻辑“或”,只有当一个条件为真时,整个表达式为真。-a
:表示逻辑“与”,只有当两个条件都为真时,整个表达式才为真。!
:表示逻辑“非”,用来取反条件表达式的结果。
布尔运算符非常有用,尤其是在复杂的条件判断中,可以使脚本更具灵活性。
字符串运算符
在 Shell 脚本中,字符串运算符用于对字符串进行比较和操作。常用的字符串运算符有以下几种:
运算符 | 说明 | 示例 |
---|---|---|
= | 字符串相等(判断两个字符串是否相等) | if [ "$a" = "$b" ] |
!= | 字符串不相等 | if [ "$a" != "$b" ] |
-z | 判断字符串是否为空(空字符串返回 true) | if [ -z "$a" ] |
-n | 判断字符串是否非空(非空字符串返回 true) | if [ -n "$a" ] |
示例:字符串比较
判断字符串是否相等
#!/bin/bash
a="abc"
b="efg"
if [ "$a" = "$b" ]; then
echo "a 等于 b"
else
echo "a 不等于 b"
fi
# 输出:a 不等于 b
判断字符串是否不相等
#!/bin/bash
a="abc"
b="efg"
if [ "$a" != "$b" ]; then
echo "a 不等于 b"
else
echo "a 等于 b"
fi
# 输出:a 不等于 b
判断字符串是否为空
#!/bin/bash
a=""
if [ -z "$a" ]; then
echo "字符串为空"
else
echo "字符串非空"
fi
# 输出:字符串为空
判断字符串是否非空
#!/bin/bash
a="abc"
if [ -n "$a" ]; then
echo "字符串非空"
else
echo "字符串为空"
fi
# 输出:字符串非空
总结
=
:用于判断两个字符串是否相等。!=
:用于判断两个字符串是否不相等。-z
:用于判断字符串是否为空。-n
:用于判断字符串是否非空。
字符串运算符非常适合用于进行条件判断,帮助脚本实现更复杂的逻辑。
文件相关运算符
使用方式很简单,比如我们定义好了一个文件路径file="/usr/learnshell/test.sh"
如果我们想判断这个文件是否可读,可以这样if [ -r $file ]
如果想判断这个文件是否可写,可以这样-w $file
,是不是很简单。
四、Shell 流程控制
if 条件语句
在 Shell 编程中,if
语句用于根据条件的真假执行不同的代码。它的基本语法结构如下:
if [ 条件 ]
then
# 条件为真时执行的语句
elif [ 条件 ]
then
# 其他条件为真时执行的语句
else
# 条件都不为真时执行的语句
fi
其中:
if
后面的条件部分[ 条件 ]
是判断条件;then
后面跟着当条件为真时要执行的命令;elif
可以用于判断额外的条件;else
是所有条件都不满足时执行的部分;fi
是if
语句的结束标志。
示例:使用 if
语句判断两个数字的关系
#!/bin/bash
a=3
b=9
if [ $a -eq $b ]; then
echo "a 等于 b"
elif [ $a -gt $b ]; then
echo "a 大于 b"
else
echo "a 小于 b"
fi
输出:
a 小于 b
解释:
[ $a -eq $b ]
判断a
是否等于b
;[ $a -gt $b ]
判断a
是否大于b
;- 如果都不满足,则执行
else
部分。
注意事项:
- 在 Shell 中,
if
条件语句中不能包含空语句,即什么都不做的语句。在 Java 或 PHP 中,if
可以直接使用一个空块{}
,但是在 Shell 中必须明确指定语句。 - 条件判断时需要注意空格,
[ 条件 ]
中的方括号两边必须有空格,[条件]
会导致语法错误。
常用的条件判断操作符:
- 数字比较:
-eq
:等于-ne
:不等于-gt
:大于-lt
:小于-ge
:大于或等于-le
:小于或等于
- 字符串比较:
=
:等于!=
:不等于-z
:字符串为空-n
:字符串非空
通过这些条件判断运算符,我们可以在 Shell 中进行多种条件判断,以执行不同的操作。
for 循环语句
for
循环在 Shell 编程中用于重复执行一段代码。Shell 中的 for
循环语法较为简洁,支持多种使用方式。
示例 1: 输出当前列表中的数据
for loop in 1 2 3 4 5
do
echo "The value is: $loop"
done
输出:
The value is: 1
The value is: 2
The value is: 3
The value is: 4
The value is: 5
在这个例子中,for
循环遍历 1 2 3 4 5
列表中的每个数字,每次迭代将数字赋值给变量 loop
,并执行 echo
命令输出当前的值。
示例 2: 产生 10 个随机数
#!/bin/bash
for i in {0..9};
do
echo $RANDOM;
done
输出:
13828
43812
63194
28219
14003
... # 更多随机数
在这个例子中,for
循环会从 0
到 9
执行 10 次,每次迭代输出一个随机数。
示例 3: 输出 1 到 5
#!/bin/bash
length=5
for ((i=1;i<=length;i++)); do
echo $i
done
输出:
1
2
3
4
5
在这个示例中,for
循环使用了 C 风格的语法,使用 (( ))
包围条件和语句。循环从 i=1
开始,到 i=5
为止,每次增加 1,并输出当前的 i
。
总结:
- 简洁的列表遍历:可以直接在
for
后面指定要遍历的列表,如1 2 3 4 5
。 - C 风格的循环:使用
(( ))
可以实现更灵活的循环控制(包括初始化、条件判断和步长)。 - 随机数生成:利用
$RANDOM
可以在循环中生成随机数,进行更复杂的操作。
for
循环语句是 Shell 编程中非常常见的一种控制结构,适用于各种重复性任务。
while 语句
while
循环用于在条件为 true
时反复执行一段代码,直到条件不再满足为止。
示例 1: 基本的 while
循环语句
#!/bin/bash
int=1
while(( $int<=5 ))
do
echo $int
let "int++"
done
输出:
1
2
3
4
5
在这个例子中,while
循环通过条件 (( $int<=5 ))
来判断是否继续执行。每次迭代时,let "int++"
使变量 int
自增 1,直到 int
的值超过 5,循环结束。
示例 2: while
循环用于读取键盘输入
echo '按下 <CTRL-D> 退出'
echo -n '输入你最喜欢的电影: '
while read FILM
do
echo "是的!$FILM 是一个好电影"
done
输出:
按下 <CTRL-D> 退出
输入你最喜欢的电影: 变形金刚
是的!变形金刚 是一个好电影
输入你最喜欢的电影: 泰坦尼克号
是的!泰坦尼克号 是一个好电影
...
在这个示例中,while
循环通过 read
命令持续读取用户的输入,并在每次输入后输出一条消息。当用户按下 CTRL-D
时,输入结束,循环退出。
示例 3: 无限循环
while true
do
command
done
解释:
此代码会创建一个无限循环,不会停止,直到外部中断(例如按 CTRL+C
)。true
是一个始终返回 true
的命令,因此循环永远不会结束。
总结:
while
循环的关键是通过条件控制执行,条件为true
时循环继续,直到条件不再满足。while
循环可以用于读取键盘输入、文件内容等。- 无限循环通常用于需要一直运行的进程,直到被外部信号中断。
五、Shell 函数
不带参数没有返回值的函数
这是一个简单的示例,演示如何定义一个不带参数且没有返回值的 Shell 函数。函数通过 echo
输出信息。
示例:
#!/bin/bash
hello(){
echo "这是我的第一个 shell 函数!"
}
echo "-----函数开始执行-----"
hello
echo "-----函数执行完毕-----"
输出结果:
-----函数开始执行-----
这是我的第一个 shell 函数!
-----函数执行完毕-----
解释:
hello
是一个简单的函数,它没有参数和返回值。- 函数体内使用
echo
打印消息"这是我的第一个 shell 函数!"
。 - 在调用函数
hello
时,Shell 执行该函数并打印相应的输出。 - 通过
echo
可以打印函数执行的开始和结束,帮助调试和控制输出流。
此类函数一般用于执行一些固定的、无需传递参数的任务。
有返回值的函数
在 Shell 中,函数可以通过 return
语句返回一个整数值。然而需要注意的是,return
只能返回 0 到 255 之间的整数。如果你需要返回更大的数值或字符串,可以通过 echo
输出结果,然后在调用时捕获该输出。
示例:输入两个数字并返回它们的和
#!/bin/bash
funWithReturn(){
echo "输入第一个数字: "
read aNum
echo "输入第二个数字: "
read anotherNum
echo "两个数字分别为 $aNum 和 $anotherNum !"
return $(($aNum+$anotherNum))
}
funWithReturn
echo "输入的两个数字之和为 $?"
输出结果:
输入第一个数字:
1
输入第二个数字:
2
两个数字分别为 1 和 2 !
输入的两个数字之和为 3
解释:
funWithReturn
是一个带返回值的函数,用户输入两个数字。- 使用
read
获取用户输入的数字,并将它们相加。 return $(($aNum+$anotherNum))
计算两个数字之和并通过return
返回。注意:return
返回的是退出状态码,范围为 0 到 255。因此,该方法适用于返回小于 255 的数值。- 使用
$?
获取上一个命令的返回值,在这里是函数的返回值。
注意:
对于需要返回较大数值或字符串的情况,推荐使用 echo
输出结果,并使用命令替换($(...)
)捕获输出。
#!/bin/bash
funWithReturn(){
echo "输入第一个数字: "
read aNum
echo "输入第二个数字: "
read anotherNum
echo "两个数字分别为 $aNum 和 $anotherNum !"
echo $(($aNum+$anotherNum)) # 通过 echo 输出返回值
}
result=$(funWithReturn)
echo "输入的两个数字之和为 $result"
带参数的函数
在 Shell 中,函数可以接收多个参数。通过 $1
, $2
, ..., $n
来引用传递给函数的参数。需要注意的是,当参数的个数超过 9 时,必须使用花括号 ${}
来正确引用。
示例:带参数的函数
#!/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
输出结果:
第一个参数为 1 !
第二个参数为 2 !
第十个参数为 10 !
第十个参数为 34 !
第十一个参数为 73 !
参数总数有 11 个!
作为一个字符串输出所有参数 1 2 3 4 5 6 7 8 9 34 73 !
解释:
$1
,$2
, ...,$n
:用于访问传递给函数的参数。$1
表示第一个参数,$2
表示第二个参数,以此类推。$(($a+$b))
:如果需要操作数字,可以直接通过$
来引用。${10}
:当参数个数超过 9 时,$10
会被视作$1
和0
的合并,导致不正确的结果。为了正确引用第 10 个参数,应该使用${10}
,以此避免混淆。$#
:表示传递给函数的参数个数。$*
:表示所有的参数,会将所有的参数作为一个单独的字符串输出。
通过这种方式,我们可以处理多个传递给函数的参数,并灵活地在 Shell 脚本中使用它们。