Shell脚本编程入门:从零基础到实战掌握

引言

作为一名后端开发者,掌握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中定义存储自定义全局共享环境变量数据

创建环境变量步骤

  1. 编辑/etc/profile全局配置文件,增加命令:定义变量VAR1=VAR1并导出为环境变量。
  2. 重载配置文件/etc/profile,因为配置文件修改后要立刻加载里面的数据就需要重载,语法:source /etc/profile
  3. 在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环境

  1. 直接登录加载Shell登录环境。
  2. su切换用户加载Shell登录与Shell非登录环境
    • 语法1(加载登录环境):su 用户名 --loginsu 用户名 -l
    • 语法2(加载非登录环境):su 用户名
  3. 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 ....)

注意赋值号=两边不能有空格

演示

  1. 定义数组存储多个数字:nums=(29 100 13 8 91 44)
  2. Shell是弱类型的,它并不要求所有数组元素的类型必须一致:
bash 复制代码
arr=(20 56 "http://www.itcast.cn/")
# Shell数组元素定义后不是固定的,定义后还可以赋值
arr[6]=100
  1. 可以给指定元素赋值初始化:
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
相关推荐
东东5162 小时前
校园短期闲置资源置换平台 ssm+vue
java·前端·javascript·vue.js·毕业设计·毕设
qq_419854052 小时前
富文本编辑器
前端
悟能不能悟2 小时前
VUE的国际化,怎么实现
前端·javascript·vue.js
Mr Xu_2 小时前
解决 Vue + Axios 热更新导致响应拦截器重复注册的问题
前端·javascript·vue.js
岁岁种桃花儿2 小时前
NodeJs从入门到上天:什么是Node.js
前端·node.js
colicode2 小时前
语音报警接口开发参考:紧急情况下快速调用语音API发送安全警报
前端·语音识别
夏河始溢2 小时前
一八四、Zustand 状态管理详解、与 Redux、MobX 的对比分析
前端·javascript·react.js·状态管理·zustand
Code小翊2 小时前
TypeScript 核心语法速查
前端·javascript·typescript
家里有只小肥猫2 小时前
uniApp下拉渐变头部 拿来即用
前端·javascript·uni-app