引言
作为一名后端开发者,掌握Shell脚本编程是必备技能。无论是日常的服务器运维、自动化部署,还是数据处理,Shell脚本都能大大提高工作效率。本文从零开始,带你系统学习Shell脚本编程。
第一章 Shell概述
通俗理解 :Shell既是「命令翻译官」,也是「编程语言」,核心作用如下:
命令解释器:接收用户/应用程序的命令,传递给操作系统内核执行,相当于用户和Linux内核之间的桥梁。编程语言:语法简单、易编写调试、灵活性强,可将一系列命令组合成脚本,实现自动化操作。

1.1 Linux中的Shell解析器
Linux系统提供多种Shell解析器,可通过以下命令查看所有可用解析器:
bash
[root@node1 ~]# cat /etc/shells
/bin/sh
/bin/bash
/usr/bin/sh
/usr/bin/bash
/bin/tcsh
/bin/csh
1.2 bash与sh的关系
CentOS中,sh是bash的软链接(相当于快捷方式),默认解析器是bash:
bash
# 查看bash相关文件,确认软链接关系
[root@node1 ~]# ls -l /bin/ | grep bash
-rwxr-xr-x. 1 root root 964536 Nov 25 2021 bash
lrwxrwxrwx. 1 root root 10 Dec 5 2023 bashbug -> bashbug-64
-rwxr-xr-x. 1 root root 6964 Nov 25 2021 bashbug-64
lrwxrwxrwx. 1 root root 4 Dec 5 2023 sh -> bash
# 查看当前默认解析器
[root@node1 ~]# echo $SHELL
/bin/bash
提示 :bash是Bourne Shell的扩展版,兼容性强、交互性好,支持更多语法和功能,是Linux主流的Shell解析器。
1.3 常用基础命令:echo
echo用于在终端打印输出数据,是Shell脚本中最常用的命令之一:
bash
# 语法:echo 输出内容(字符串建议加双引号)
[root@node1 ~]# echo "helloworld"
helloworld
第二章 Shell脚本入门
Shell脚本是一个文本文件 (后缀名建议为.sh),可编写一系列Shell命令或编程语句,实现命令的批量执行和自动化操作。
2.1 脚本格式规范
- 首行指定解析器 :必须以
#!/bin/bash开头,告诉系统用bash解析这个脚本。 - 注释格式:
- 单行注释 :用
#开头,后面跟注释内容(#和内容之间建议加空格)。 - 多行注释 :用
:<<!开头,!结尾,中间包裹注释内容。
- 单行注释 :用
bash
# 脚本格式示例
#!/bin/bash
# 这是单行注释:第一个Shell脚本
echo "helloworld" # 打印helloworld
:<<!
这是多行注释
用于说明脚本的功能、作者、编写日期等
!
2.2 第一个脚本:helloworld.sh
需求:创建一个Shell脚本,执行后输出helloworld。
实操步骤
bash
# 1. 创建脚本文件(touch命令创建空文件)
[root@node1 ~]# touch helloworld.sh
# 2. 编辑脚本(vim编辑器,按i进入编辑模式,Esc退出编辑,:wq保存退出)
[root@node1 ~]# vim helloworld.sh
# 3. 输入脚本内容
#!/bin/bash
echo "helloworld"
2.3 脚本的3种执行方式
方式1:bash/sh + 脚本路径(无需赋权)
本质是用bash/sh解析器帮我们执行脚本,脚本本身不需要执行权限,适合快速测试。
bash
# 相对路径(脚本在当前目录下,用./开头)
[root@node1 scripts]# sh ./helloworld.sh
helloworld
[root@node1 scripts]# bash ./helloworld.sh
helloworld
# 绝对路径(从根目录开始写完整路径)
[root@node1 ~]# sh /root/scripts/helloworld.sh
helloworld
[root@node1 ~]# bash /root/scripts/helloworld.sh
helloworld
方式2:脚本路径直接执行(需赋权)
本质是让脚本自己执行,必须给脚本赋予"执行权限"(+x),是实际工作中最常用的方式。
bash
# 1. 赋予执行权限(chmod +x 脚本路径)
[root@node1 scripts]# chmod +x helloworld.sh
# 2. 执行脚本
# 相对路径
[root@node1 scripts]# ./helloworld.sh
helloworld
# 绝对路径
[root@node1 ~]# /root/scripts/helloworld.sh
helloworld
方式3:source/. + 脚本路径(无需赋权,影响当前Shell)
让脚本在当前Shell环境中执行(不打开子Shell),脚本中定义的变量、配置会直接生效于当前终端。
bash
# 示例:测试变量生效范围
# 1. 创建测试脚本test.sh
[root@node1 ~]# cat test.sh
#!/bin/bash
A=5 # 定义变量A
echo $A # 打印变量A
# 2. 不同方式执行对比
[root@node1 ~]# bash test.sh # 方式1:子Shell执行,变量不生效
5
[root@node1 ~]# echo $A # 终端中查看A,无输出(变量只在子Shell中存在)
[root@node1 ~]# source test.sh # 方式3:当前Shell执行,变量生效
5
[root@node1 ~]# echo $A # 终端中可查看A的值
5
关键点:
- 前两种方式在子shell中执行,执行完毕变量消失
- source方式在当前shell执行,变量会保留
- 修改配置文件后需要用
source使其立即生效
三种执行方式对比
| 执行方式 | 命令示例 | 是否需要执行权限 | 执行环境 |
|---|---|---|---|
| bash/sh执行 | bash helloworld.sh | ❌ 不需要 | 子shell |
| 路径直接执行 | ./helloworld.sh | ✅ 需要 | 子shell |
| source执行 | source helloworld.sh | ❌ 不需要 | 当前shell |
第三章 Shell变量
变量用于临时存储数据(运行在内存中),方便脚本中重复调用和修改,Shell变量分为系统预定义变量 、自定义变量 、特殊变量三类。
3.1 变量分类与配置文件
环境变量分类
- 系统级环境变量 :定义在全局配置文件中,所有用户、所有Shell程序都能使用。
- 用户级环境变量 :定义在个人配置文件中,只有当前用户能使用。
Shell配置文件
- 全局配置文件(所有用户生效) :
/etc/profile、/etc/profile.d/*.sh、/etc/bashrc - 个人配置文件(当前用户生效) :
~/.bash_profile、~/.bashrc(~代表当前用户主目录)
说明:工作中常修改全局配置文件,实现所有用户共享环境变量。
3.2 系统预定义变量
系统自带的变量,无需定义可直接使用,常用变量如下:
| 变量名称 | 含义 |
|---|---|
| $HOME | 当前用户主目录(如root用户是/root) |
| $PWD | 当前所在路径 |
| $SHELL | 当前使用的Shell解析器(默认/bin/bash) |
| $USER | 当前登录用户 |
| $PATH | 命令搜索路径,系统通过此变量查找可执行命令 |
| $HISTFILE | 当前用户的命令历史记录文件(默认~/.bash_history) |
| $LANG | 系统语言环境 |
实操案例
bash
# 1. 查看单个系统变量的值
[root@node1 ~]# echo $HOME
/root
[root@node1 ~]# echo $PWD
/root
# 2. 查看所有系统环境变量(env命令)
[root@node1 ~]# env
# 3. 查看所有变量(系统变量+自定义变量+函数,set命令)
[root@node1 ~]# set
3.3 自定义变量
用户根据需求自己定义的变量,分为局部变量、全局变量、常量三类。
基本语法
- 定义变量:
变量名=变量值(等号前后不能有空格) - 撤销变量:
unset 变量名 - 声明常量:
readonly 变量名=变量值(常量不可撤销、不可修改) - 提升为全局变量:
export 变量名(全局变量可在子Shell中使用)
变量定义规则
- 变量名由字母、数字、下划线组成,不能以数字开头(环境变量建议大写)。
- Shell变量默认是字符串类型,无法直接进行数值运算。
- 变量值含空格时,必须用双引号 或单引号包裹。
实操案例
bash
# 1. 定义局部变量(仅当前脚本/终端生效)
[root@node1 ~]# A=5
[root@node1 ~]# echo $A
5
# 2. 重新赋值
[root@node1 ~]# A=8
[root@node1 ~]# echo $A
8
# 3. 撤销变量
[root@node1 ~]# unset A
[root@node1 ~]# echo $A # 无输出,变量已撤销
# 4. 声明常量(不可修改、不可撤销)
[root@node1 ~]# readonly B=2
[root@node1 ~]# echo $B
2
[root@node1 ~]# B=9 # 尝试修改,报错
-bash: B: readonly variable
# 5. 变量值含空格(需用引号包裹)
[root@node1 ~]# D="I love banzhang"
[root@node1 ~]# echo $D
I love banzhang
# 6. 提升为全局变量(供子Shell使用)
[root@node1 ~]# export B # 将常量B提升为全局变量
[root@node1 ~]# bash # 进入子Shell
[root@node1 ~]# echo $B # 可查看全局变量B的值
2
3.4 特殊变量
Shell内置的特殊变量,主要用于处理脚本参数、命令执行结果等,高频使用需牢记。
3.4.1 $n:获取脚本参数
- 语法:
$n(n为数字,0代表脚本名称,`1-9`代表第1-9个参数,10及以上需用`{10}`)。 - 用法:执行脚本时,紧跟脚本路径传入参数。
bash
# 1. 创建脚本parameter.sh
[root@node1 scripts]# vim parameter.sh
#!/bin/bash
echo "脚本名称:$0"
echo "第一个参数:$1"
echo "第二个参数:$2"
# 2. 执行脚本并传入参数
[root@node1 scripts]# ./parameter.sh a b
脚本名称:./parameter.sh
第一个参数:a
第二个参数:b
3.4.2 $#:获取参数个数
用于判断传入参数的个数是否符合要求,提升脚本健壮性。
bash
# 修改parameter.sh
#!/bin/bash
echo "脚本名称:$0"
echo "第一个参数:$1"
echo "第二个参数:$2"
echo "参数总个数:$#"
# 执行脚本
[root@node1 scripts]# ./parameter.sh a b c
脚本名称:./parameter.sh
第一个参数:a
第二个参数:b
参数总个数:3
3.4.3 $* 与 $@:获取所有参数
两者都能获取所有传入参数,核心区别在于是否加双引号:
- 不加双引号:功能一致,均以"
$1 $2 ... $n"格式输出所有参数。 - 加双引号:
$*将所有参数拼接为一个字符串;$@保留每个参数的独立性,视为多个字符串。
bash
# 修改parameter.sh
#!/bin/bash
echo "====== \$* 测试 ======"
for parm in "$*"
do
echo $parm
done
echo "====== \$@ 测试 ======"
for parm in "$@"
do
echo $parm
done
# 执行脚本
[root@node1 scripts]# ./parameter.sh a b c
====== $* 测试 ======
a b c
====== $@ 测试 ======
a
b
c
3.4.4 $?:获取命令执行结果状态
判断上一条命令是否执行成功,是脚本中错误处理的核心变量:
- 返回值为
0:上一条命令执行成功。 - 返回值为
非0:上一条命令执行失败(具体数值由命令自身定义)。
bash
# 执行成功的命令,查看$?
[root@node1 ~]# echo "helloworld"
helloworld
[root@node1 ~]# echo $?
0
# 执行失败的命令,查看$?
[root@node1 ~]# cat test123.sh # 不存在的文件
cat: test123.sh: No such file or directory
[root@node1 ~]# echo $?
1
3.5 环境变量深入
3.5.1 自定义系统环境变量
全局配置文件/etc/profile应用场景
- 当前用户进入Shell环境初始化的时候会加载全局配置文件
/etc/profile里面的环境变量,供给所有Shell程序使用。 - 以后只要是所有Shell程序或命令使用的变量,就可以定义在这个文件中。
案例演示
需求:在/etc/profile中定义存储自定义全局共享环境变量数据
创建环境变量步骤
- 编辑
/etc/profile全局配置文件,增加命令:定义变量VAR1=VAR1并导出为环境变量。 - 重载配置文件/etc/profile,因为配置文件修改后要立刻加载里面的数据就需要重载,语法:
source /etc/profile。 - 在Shell环境中读取系统级环境变量
VAR1。
3.5.2 加载流程原理介绍
Shell工作环境介绍
用户进入Linux系统就会初始化Shell环境,这个环境会加载全局配置文件 和用户个人配置文件中环境变量,每个脚本文件都有自己的Shell环境。
Shell工作环境分类
交互式与非交互式Shell
- 交互式Shell:与用户进行交互,互动效果就是用户输入一个命令,Shell环境立刻反馈响应。
- 非交互式Shell:不需要用户参与就可以执行多个命令,比如一个脚本文件含有多个命令,直接执行并给出结果。
登录Shell与非登录Shell环境
- Shell登录环境:需要用户名、密码登录的Shell环境。
- Shell非登录环境:不需要用户名、密码进入的Shell环境或执行脚本文件。
注意:不同的工作环境加载环境变量流程不一样。
如何识别Shell环境类型?
使用$0识别环境语法:echo $0
- 输出
-bash代表:Shell登录环境 - 输出
bash代表:Shell非登录环境
注意:这个$0环境变量如果用在子Shell中(Shell脚本文件),会输出Shell脚本本身的文件名。
bash命令语法
bash:用于切换为Shell非登录环境。
详细切换Shell环境
- 直接登录加载Shell登录环境。
su切换用户加载Shell登录与Shell非登录环境- 语法1(加载登录环境):
su 用户名 --login或su 用户名 -l - 语法2(加载非登录环境):
su 用户名
- 语法1(加载登录环境):
- bash加载Shell登录与Shell非登录环境。
3.6 字符串与数组变量(拓展)
3.6.1 字符串变量
字符串是Shell中最常用的数据类型,有3种定义格式,核心区别在于变量解析和空格处理:
- 单引号 :原样输出所有内容,不解析变量。
- 双引号 :解析变量,支持转义字符(推荐使用)。
- 无引号 :解析变量,但不支持空格(空格后内容会被视为命令)。
bash
# 字符串常用操作
[root@node1 ~]# var="rapden"
# 1. 计算字符串长度
[root@node1 ~]# echo ${#var}
6
# 2. 字符串拼接
[root@node1 ~]# var1="hi"
[root@node1 ~]# var2="${var1} ${var}" # 双引号拼接(推荐)
[root@node1 ~]# echo $var2
hi rapden
# 3. 字符串截取(${变量名:起始位置:长度},起始位置从0开始)
[root@node1 ~]# echo ${var:1:3} # 从第2个字符开始,截取3个
apd
3.6.1.1 常用方法
获取字符串的长度
语法:${#字符串变量名}
bash
[userA@node1 ~]$ var1=rapden
[userA@node1 ~]$ echo ${#var1}
6
字符串拼接
字符串拼接方式:无符号拼接、双引号拼接、混合拼接
bash
[root@node1 ~]# var1=hi
[root@node1 ~]# var2="hello world"
[root@node1 ~]# var3=${var1}${var2}
[root@node1 ~]# echo ${var3}
hihello world
[root@node1 ~]# var3="${var1} ${var2}"
[root@node1 ~]# echo $var3
hi hello world
[root@node1 ~]# var3=${var1}'&'${var3}
[root@node1 ~]# echo ${var3}
hi&hi hello world
字符串截取
${变量名:start:length}:从string字符串的左边第start个字符开始,向右截取length个字符(start从0开始)。${变量名:start}:从string字符串的左边第start个字符开始截取,直到最后。${变量名:0-start:length}:从string字符串的右边第start个字符开始,向右截取length个字符(start从1开始,代表右侧第一个字符)。${变量名:0-start}:从string字符串的右边第start个字符开始截取,直到最后。${变量名#*chars}:从string字符串左边第一次出现chars的位置开始,截取chars右边的所有字符。${变量名##*chars}:从string字符串左边最后一次出现chars的位置开始,截取chars右边的所有字符。${变量名%chars*}:从string字符串右边第一次出现chars的位置开始,截取chars左边的所有字符。${变量名%%chars*}:从string字符串右边最后一次出现chars的位置开始,截取chars左边的所有字符。
3.6.2 数组变量
Shell仅支持一维数组,用于存储多个数据,元素之间用空格 分隔。
数组的定义
语法
在Shell中,用括号()来表示数组,数组元素之间用空格来分隔,语法为:
- 方式1:
array_name=(item1 item2...) - 方式2:
array_name=([索引下标1]=item1 [索引下标2]=item2 ....)
注意 ,赋值号=两边不能有空格。
演示
- 定义数组存储多个数字:
nums=(29 100 13 8 91 44) - Shell是弱类型的,它并不要求所有数组元素的类型必须一致:
bash
arr=(20 56 "http://www.itcast.cn/")
# Shell数组元素定义后不是固定的,定义后还可以赋值
arr[6]=100
- 可以给指定元素赋值初始化:
bash
arr2=([0]=1 [2]=100 [4]=a)
# 由于只赋值了3个元素,所以数组的长度是3
数组的获取
- 通过下标获取元素值,index从
0开始,注意使用{}:${arr[index]} - 获取值同时复制给其他变量:
item=${arr[index]} - 使用
@或*可以获取数组中的所有元素:${arr[@]}、${arr[*]} - 获取数组的长度或个数:
${#arr[@]}、${#arr[*]} - 获取数组指定元素的字符长度:
${#arr[索引]}
数组的拼接
数组拼接(合并),就是将两个数组连接成一个数组,使用@和*获取数组所有元素之后进行拼接:
bash
array_new=(${array1[@]} ${array2[@]})
array_new=(${array1[*]} ${array2[*]})
数组的删除
删除数组指定元素和删除整个数组数据
语法
- 删除数组指定元素数据:
unset array_name [index] - 删除整个数组:
unset array_name
bash
# 1. 定义数组
[root@node1 ~]# nums=(29 100 13 8) # 方式1:直接赋值
[root@node1 ~]# arr=([0]=1 [2]=100 [4]=a) # 方式2:指定下标赋值
# 2. 获取数组元素
[root@node1 ~]# echo ${nums[0]} # 获取下标为0的元素
29
[root@node1 ~]# echo ${nums[@]} # 获取所有元素
29 100 13 8
# 3. 获取数组长度
[root@node1 ~]# echo ${#nums[@]}
4
# 4. 删除数组元素/数组
[root@node1 ~]# unset nums[1] # 删除下标为1的元素
[root@node1 ~]# unset nums # 删除整个数组
第四章 Shell运算符与条件判断
4.1 数值运算
Shell变量默认是字符串类型,需用特定语法实现数值运算,常用两种方式:
- 语法1:
$((运算式))(推荐,简洁易懂) - 语法2:
$[运算式](兼容所有bash版本)
bash
# 案例:计算(2+3)*4
[root@node1 ~]# a=$(( (2+3)*4 ))
[root@node1 ~]# echo $a
20
# 案例:累加计算
[root@node1 ~]# b=$[ 10+20+30 ]
[root@node1 ~]# echo $b
60
4.2 条件判断
用于判断变量值、文件状态、权限等,是流程控制的基础,有两种基本语法:
- 语法1:
test 条件 - 语法2:
[ 条件 ](条件前后必须有空格,最常用)
注意 :条件非空即为真,[ atguigu ] 返回真,[] 返回假,判断结果可通过$?查看。
常用判断条件
(1)整数比较
用于两个整数的大小比较,不能直接用>、<(会被视为字符串比较):
| 符号 | 含义 |
|---|---|
| -eq | 等于(equal) |
| -ne | 不等于(not equal) |
| -lt | 小于(less than) |
| -le | 小于等于(less equal) |
| -gt | 大于(greater than) |
| -ge | 大于等于(greater equal) |
(2)字符串比较
- 等于:
[ 字符串1 = 字符串2 ](等号前后有空格) - 不等于:
[ 字符串1 != 字符串2 ]
(3)文件权限判断
| 符号 | 含义 |
|---|---|
| -r | 文件有读权限(read) |
| -w | 文件有写权限(write) |
| -x | 文件有执行权限(execute) |
(4)文件类型判断
| 符号 | 含义 |
|---|---|
| -e | 文件存在(existence) |
| -f | 文件存在且是普通文件(file) |
| -d | 文件存在且是目录(directory) |
实操案例
bash
# 1. 整数比较:23是否大于等于22
[root@node1 ~]# [ 23 -ge 22 ]
[root@node1 ~]# echo $? # 返回0,说明条件成立
0
# 2. 文件权限判断:helloworld.sh是否有写权限
[root@node1 ~]# [ -w helloworld.sh ]
[root@node1 ~]# echo $?
0
# 3. 文件类型判断:/home/cls.txt是否存在
[root@node1 ~]# [ -e /home/cls.txt ]
[root@node1 ~]# echo $? # 返回1,说明文件不存在
1
# 4. 多条件判断(&&:前一条成功才执行后一条;||:前一条失败才执行后一条)
[root@node1 ~]# [ 23 -ge 22 ] && echo "条件成立" || echo "条件不成立"
条件成立
第五章 流程控制语句(重点)
流程控制用于控制脚本中命令的执行顺序,核心包括if判断 、case分支 、for循环 、while循环,是编写复杂脚本的基础。
5.1 if 判断
根据条件是否成立,执行不同的命令,分为单分支 、多分支两种场景。
基本语法
(1)单分支
bash
if [ 条件判断式 ]; then
命令序列 # 条件成立时执行
fi
# 或(换行格式,更易读)
if [ 条件判断式 ]
then
命令序列
fi
(2)多分支
bash
if [ 条件判断式1 ]
then
命令序列1 # 条件1成立时执行
elif [ 条件判断式2 ]
then
命令序列2 # 条件2成立时执行
else
命令序列3 # 所有条件都不成立时执行
fi
实操案例
bash
# 创建脚本testif.sh
[root@node1 scripts]# vim testif.sh
#!/bin/bash
# 判断第一个参数是否为rapden
if [ "$1"x = "rapden"x ]
then
echo "hello,rapden!"
fi
# 判断第二个参数(年龄)所属年龄段
if [ $2 -lt 18 ]
then
echo "未成年人"
elif [ $2 -lt 35 ]
then
echo "青年人"
elif [ $2 -lt 60 ]
then
echo "中年人"
else
echo "老年人"
fi
# 执行脚本
[root@node1 scripts]# ./testif.sh rapden 25
hello,rapden!
青年人
提示 :判断字符串时,加x(如"$1"x = "rapden"x)是为了避免参数为空时报错,提升脚本健壮性。
5.2 case语句
用于多值匹配场景,根据变量的不同取值,执行对应的命令,比多分支if更简洁。
基本语法
bash
case $变量名 in
"值1")
命令序列1 # 变量等于值1时执行
;; # 结束当前分支(相当于break)
"值2")
命令序列2 # 变量等于值2时执行
;;
... # 可添加多个分支
*) # 默认分支(变量不匹配任何值时执行)
命令序列n
esac
注意事项
- case行尾必须跟
in,每个分支的匹配值必须用双引号包裹,结尾用)。 - 双分号
;;不能省略,用于结束当前分支,防止执行后续分支。 *)是默认分支,必须放在最后。
实操案例
bash
# 创建脚本case_test.sh
[root@node1 scripts]# vim case_test.sh
#!/bin/bash
# 输入一个数字,输出对应的英文
case $1 in
1)
echo "one"
;;
2)
echo "two"
;;
3)
echo "three"
;;
*)
echo "number else"
;;
esac
# 执行脚本
[root@node1 scripts]# ./case_test.sh 1
one
[root@node1 scripts]# ./case_test.sh 7
number else
5.3 for循环
用于重复执行一系列命令,分为两种语法,适用于不同场景。
语法1:数值循环(适合固定次数循环)
bash
for (( 初始值; 循环控制条件; 变量变化 ))
do
命令序列 # 循环体,每次循环执行
done
实操案例:1加到10
bash
# 创建脚本for_test.sh
[root@node1 scripts]# vim for_test.sh
#!/bin/bash
sum=0 # 定义变量存储累加结果
for (( i=1; i<=10; i++ )) # i从1到10,每次加1
do
sum=$[ $sum + $i ] # 累加计算
done
echo "1到10的和:$sum"
# 执行脚本
[root@node1 scripts]# ./for_test.sh
1到10的和:55
语法2:列表循环(适合遍历数组、参数等)
bash
for 变量 in 值1 值2 值3...
do
命令序列 # 变量依次取列表中的值,执行一次循环体
done
实操案例
bash
# 1. 遍历字符串列表
[root@node1 ~]# for os in linux windows macos; do echo $os; done
linux
windows
macos
# 2. 遍历数字范围(1到100),计算累加和
[root@node1 ~]# sum=0; for i in {1..100}; do sum=$[$sum+$i]; done; echo $sum
5050
# 3. 遍历脚本参数(结合$@)
[root@node1 scripts]# vim param_test.sh
#!/bin/bash
echo "所有参数:"
for parm in "$@"
do
echo $parm
done
[root@node1 scripts]# ./param_test.sh a b c d
所有参数:
a
b
c
d
5.4 while循环
根据条件是否成立,重复执行循环体,适合不确定循环次数的场景(如根据用户输入循环)。
基本语法
bash
while [ 条件判断式 ]
do
命令序列 # 条件成立时,执行循环体
done
实操案例:1加到100
bash
# 创建脚本while_test.sh
[root@node1 scripts]# vim while_test.sh
#!/bin/bash
a=1 # 初始值
sum=0 # 累加结果
while [ $a -le 100 ] # 条件:a小于等于100
do
let sum+=a # 等价于sum=$[sum+a],简洁写法
let a++ # 等价于a=$[a+1],a自增1
done
echo "1到100的和:$sum"
# 执行脚本
[root@node1 scripts]# ./while_test.sh
1到100的和:5050