网站前台登录模板,土石方工程网站,wordpress相关阅读禁止显示图片,重庆宣传片细致观看可以#xff0c;访问shell脚本学习专栏#xff0c;对应章节会有配图https://blog.csdn.net/2201_75446043/category_12833287.html?spm1001.2014.3001.5482
导语
一、shell脚本简介
1. 定义#xff1a;
2. 主要特点#xff1a;
3. shell脚本的基本结构
4. S…细致观看可以访问shell脚本学习专栏对应章节会有配图https://blog.csdn.net/2201_75446043/category_12833287.html?spm1001.2014.3001.5482
导语
一、shell脚本简介
1. 定义
2. 主要特点
3. shell脚本的基本结构
4. Shebang
二、创建执行
1.脚本的创建
2. 脚本的执行
2.1.chmod
2.2. 使用脚本解释器直接运行脚本
2.3.source
3. 解释器的作用
三、变量
1. 定义变量
2. 引用变量
3. set 命令查看变量
4. 通过grep来筛选内容
命令解释
5.删除变量
6. 永久环境变量
6. 1. 常见的环境变量
6.2. 设置永久环境变量
6.2.1.将脚本加进PATH变量的目录中
6.2.2.添加进环境变量里
6.2.2.修改用户的 shell 配置文件
四、字符串操作
1. 字符串拼接
2.字符串切片
3. 字符串查找
4. 字符串替换
5. 字符串大小写转换
6. 字符串分割
7. 去除空白
8. 字符串长度
9. 其他常见字符串操作
五、数值的运算
1. 常见运算符
2.使用 $(( )) 进行算术运算
3. 使用 let命令进行算术运算
4. 使用expr进行算术运算
5. 浮点数运算
6. 数学运算赋值给变量
6.1. 使用 $(( )) 进行运算并赋值
6.2. 使用 let 进行运算并赋值
6.3. 使用 expr 进行运算并赋值
7. 使用 let和 $(( ))的区别
8. 数值运算段落小结
六、脚本与用户交互
1.命令行参数传递
1.1.获取的特殊变量
1.2.示例
2. read命令交互
2.1.基本语法
2.2.常用参数和选项
2.3.使用多个变量
七、if 条件判断
1.基本语法
2.多条件判断语法
2.1if-elif-else 语句
3. 关系运算符
3.1. 数值比较运算符
3.1.2. 示例数值比较
3.2. 字符串比较运算符
3.2.1.示例字符串比较
4. 逻辑运算符
4.1. 常用逻辑运算符
4.1.1. 示例逻辑与AND运算符
4.1.3. 示例逻辑或OR运算符
4.1.4.示例逻辑非!运算符
4.1.4.1.判断一个文件是否不存在。
4.1.4.2.判断命令执行是否失败
5. if 语句的结合 read和参数传递
5.1. 示例if判断结合read完成登录校验功能
5.2. 示例根据参数判断并结合 read
6. if条件判断段落小结
八、循环
1. for 循环
1.1.for循环语法
1.2.示例遍历数字列表
1.3.示例使用命令输出作为列表
2. while 循环
2.1. while 循环语法
2.2.示例计数循环
2.3.示例直到某个条件满足为止
3. until 循环
3.1.代码功能概述
3.2.循环条件分析
3.3.执行过程
4.case 语句
4.1.代码功能概述
4.2.循环条件分析
5.总结对比
九、函数
1. 函数的定义与使用
2. 函数的传参
3. 局部变量local
3.1.为什么使用 local
4. 函数返回值
5. 函数中的递归调用
递归示例计算阶乘
6. 内建函数与外部函数的区别
十、不同脚本的互相调用
1.直接调用
2.使用 source 或 . 命令
3.使用 bash 命令调用
4.传递参数给脚本
十一、重定向操作
1.输出重定向
2.追加输出
3.输入重定向
4.错误输出重定向2
5.同时重定向标准输出和标准错误
6.文件描述符介绍
6.1.重定向文件描述符
6.2.使用 exec 进行更复杂的重定向
结语
往期文章
shell脚本_创建执行与变量的定义与使用-CSDN博客
shell脚本_永久环境变量和字符串操作和shell如何变成永久变量-CSDN博客
shell脚本_脚本参数传递与数学运算-CSDN博客
shell脚本_脚本与用户交互以及if条件判断-CSDN博客
shell脚本_if条件判断与for循环结构讲解与示例-CSDN博客
shell脚本_for循环与while循环讲解和对比-CSDN博客
shell脚本_until循环和case语句与函数的定义和使用-CSDN博客
shell脚本_不同脚本的互相调用和重定向操作-CSDN博客 学习视频泷羽sec
泷羽sec的个人空间-泷羽sec个人主页-哔哩哔哩视频https://space.bilibili.com/350329294 导语
在这篇总结篇中我们将回顾和总结前面学习的 Shell 脚本基础知识。Shell 脚本是系统管理、自动化任务执行和日常操作中不可或缺的一部分掌握它将帮助我们提高工作效率和系统操作的灵活性。从最基础的变量定义和条件判断到复杂的循环结构和函数使用Shell 脚本提供了强大而灵活的工具让我们能够快速完成任务。在本篇文章中我们将对这些内容进行系统的总结帮助大家在实际工作中更好地运用 Shell 脚本。 一、shell脚本简介
Shell脚本是一个由一系列Shell命令、控制结构和逻辑语句组成的脚本文件用于在类Unix操作系统中自动化执行一系列任务。它通过Shell如Bash、Zsh、Sh等解释执行通常用于系统管理、文件操作、批处理任务以及自动化工作流等场景。
1. 定义
Shell脚本是一个包含多个命令和程序逻辑的文本文件通过Shell命令行解释器解释执行旨在自动化或简化日常任务。
2. 主要特点 命令自动化Shell脚本可以将多个Shell命令组合成一个自动化脚本避免手动输入命令。 文本文件脚本本质上是一个文本文件可以使用任何文本编辑器如Vim、Nano、VS Code等编辑。 解释执行Shell脚本并不需要事先编译它由Shell解释器直接执行通常通过命令行终端运行。 系统管理与自动化常用于自动化系统管理任务如备份、文件处理、日志分析等以及批处理操作。
3. shell脚本的基本结构 Shebang指定解释器。 注释描述脚本功能或解释代码。 命令实现脚本功能的核心部分。 变量存储和操作数据。 控制结构如条件判断和循环控制程序流。 函数组织代码提升可复用性。 输入输出与用户交互并处理数据。 退出状态通过状态码反馈执行结果。
4. Shebang
Shebang是Shell脚本的第一行用于指定脚本应由哪个解释器执行。在Linux和Unix系统中Shebang通常以 #! 开头后面跟着解释器的路径。 示例#!/bin/bash 这行指示系统使用 /bin/bash 作为解释器来执行这个脚本。 常见Shebang #!/bin/bash使用Bash解释器最常见 #!/bin/sh使用系统默认Shell通常是Bash或Dash #!/usr/bin/env python3用于Python脚本指定Python解释器。 二、创建执行
1.脚本的创建 可以用touch或者echo命令来创建sh文件 可以使用任何文本编辑器如 nano, vi, vim, gedit, emacs 等来创建脚本文件。 2. 脚本的执行
在默认情况下我们创建的脚本是没有权限被执行的。如果不明白看往期章节关于文件的权限部分Linux基础-常用操作命令详讲
这里有两种方案
2.1.chmod
Shell脚本文件本身需要具有“可执行”权限。使用 chmod 命令你可以赋予脚本文件适当的权限使得它能够被系统执行。 chmod x script.sh x 表示给文件添加“执行”权限。 script.sh 是你的Shell脚本文件名。
2.2. 使用脚本解释器直接运行脚本
如果你的脚本没有执行权限但你知道它是有效的Shell脚本你可以直接通过指定解释器通过它们可以运行脚本内容无论脚本本身是否有执行权限。 /bin/bash script.sh # 使用 Bash 解释器执行脚本 /bin/sh script.sh # 使用默认的 Bourne shell 执行脚本 /bin/dash script.sh # 使用 Dash shell 执行脚本
这三种其实不管用哪种脚本解释器最后调用的还是bash。
2.3.source source 命令会读取并执行一个文件中的内容所有在该脚本中定义的变量、函数、或者更改的环境设置都会保留在当前 shell 中。 source 可以用来重新加载配置文件或在当前 shell 中运行脚本保持环境的连续性。 它和sh的区别是存在颜色加深会显示如原本命令的目录颜色、文件颜色。 source script.sh 3. 解释器的作用
在Linux和类Unix系统中解释器Interpreter是一个将脚本文件例如Shell脚本中的代码逐行翻译并执行的程序。 /bin/bash、/bin/sh 和 /bin/dash 都是不同的Shell解释器。
解释器的作用是将脚本中的命令逐行解析并执行因此即使脚本文件本身没有执行权限只要你指定了合适的解释器它就能执行。 解释器负责逐行解析并执行脚本文件中的命令。常见的解释器有 /bin/bash、/bin/sh 和 /bin/dash。 直接执行脚本通过指定解释器即使文件没有执行权限你可以运行脚本。系统会通过该解释器来执行脚本内容。 /bin/sh 和 /bin/dash/bin/sh 是一个符号链接可能指向 Dash 或其他Shell这决定了脚本的执行环境。 三、变量
在 Shell 脚本中变量的定义与使用非常简单但需要注意 Shell 的语法规则。
1. 定义变量
Shell 中定义变量时变量名和等号之间不能有空格。例如
variable_namevalue
注意 变量名只能由字母、数字和下划线组成且不能以数字开头。 变量定义时不需要使用 以外的符号。 2. 引用变量
在使用变量时需要通过 $ 符号来引用它的值。例如
echo $name
echo $age
如果需要在变量引用中包含更多文本或者字符可以使用花括号 {} 来确保正确的解析。例如
echo My name is ${name} and I am ${age} years old.
PS:多变量必须由双引号包裹或不包裹变量名字写在${}内单引号就原模原样输出字符串不读取变量。 3. set 命令查看变量
在 Unix-like 系统如 Linux 或 macOS中set 是一个 shell 内置命令用于列出所有当前 shell 环境中的变量包括环境变量和局部变量。 列出所有变量 set 命令将显示当前 shell 环境中的所有变量包括环境变量、局部变量和 shell 特殊变量。 显示的变量包括 环境变量通过 export 设置的变量 局部变量没有使用 export 设置的变量 shell 特殊变量如 $?、\$0 等
如果你只输入 set 命令它将列出当前 shell 环境中的所有变量
set
输出会非常长包含许多信息。例如你可能会看到如下内容包含我们刚才创建的变量
BASH/bin/bash
BASH_VERSION5.0.17(1)-release
...
MY_VARHello 4. 通过grep来筛选内容
grep是一个常见的命令用于查找和筛选包含特定字符串
set | grep name
命令解释 set该命令列出当前 shell 环境中所有的变量包括环境变量和局部变量。输出的内容会非常多包括变量名和它们的值。 |管道符这个符号表示将 set 命令的输出传递给下一个命令。在这里它将 set 输出的结果传递给 grep 命令进行筛选。 grep namegrep 是一个常用的文本搜索工具它会在输入的内容中查找包含 name 的行并输出匹配的结果。
就会输出我们刚才定义的name和其他包含name的变量 5.删除变量
在 Shell 中unset 命令用于 删除变量 或 取消函数定义。当你使用 unset 删除一个变量时这个变量将不再在当前 shell 会话中有效无法再访问它。
unset name
其中 name 是你想要删除的变量的名称。 unset 删除的是当前 shell 环境中的 局部变量 或 环境变量它不会影响系统或父进程中的其他变量。 一旦变量被 unset 删除你将无法再访问它直到它被重新定义。 6. 永久环境变量
环境变量是操作系统用来存储系统和应用程序配置信息的键值对。在 Shell 脚本中环境变量的设置通常用于配置系统或应用程序的运行时环境。而永久环境变量是指那些在用户每次登录时都能自动加载的环境变量。
6. 1. 常见的环境变量
在 Linux 或 Unix 系统中永久环境变量是那些在系统启动时或用户登录时自动加载并在会话期间保持有效的环境变量。以下是一些常见的永久环境变量它们在系统中用来配置用户环境和程序行为。 1.PATH 作用定义了操作系统搜索可执行文件的目录路径。当你在命令行输入命令时Shell 会按照 PATH 中列出的目录顺序查找命令。 常见配置通过设置 PATH 环境变量可以将用户自定义的程序目录添加到搜索路径中。
export PATH$PATH:/usr/local/bin:/home/user/my_programs #设置
echo $PATH 2.HOME 作用表示当前用户的主目录。在大多数 Linux 系统中每个用户都有一个独立的主目录用于存放个人文件和配置。 echo $HOME # 输出当前用户的家目录路径 3.USER 作用表示当前登录的用户名。这个变量会自动由系统设置并用于指示当前会话的用户。 echo $USER # 输出当前登录的用户名 4.SHELL 作用指定当前用户使用的 Shell 类型。例如对于使用 Bash 的用户SHELL 的值通常是 /bin/bash。 echo $SHELL # 输出当前使用的 Shell例如 /bin/bash 6.2. 设置永久环境变量
要设置永久环境变量通常有以下几种方法
6.2.1.将脚本加进PATH变量的目录中 echo $PATH mv script.sh /usr/bin/ 将预先准备的脚本赋予权限移动到PATH变量的目录中新打开的shell窗口就可以输入该文件名执行脚本了。
6.2.2.添加进环境变量里
通过将 /root/ 目录添加到环境变量 PATH 中使得该目录下的所有可执行文件都可以直接在命令行中执行。
export PATH/root:$PATH
1.sh export PATH/root:$PATH这行命令将 /root 目录添加到当前 PATH 环境变量的前面注意 $PATH 在这里是当前环境变量的值。 /root 是你想要添加的目录。 $PATH 是现有的 PATH 环境变量包含了其他已有的目录路径。 这样当你执行一个命令时系统会首先在 /root 目录中查找可执行文件。如果该目录下有你需要的可执行文件就会优先执行该文件。 6.2.2.修改用户的 shell 配置文件 对于 Bash 用户一般修改 ~/.bashrc对于交互式非登录 shell或者 ~/.bash_profile对于登录 shell。 对于 Zsh 用户通常修改 ~/.zshrc 文件。
/usr/bin/vim /root/.bashrc
export PATH/root:$PATH
esc--:--wq(退出)
source /root/.bashrc /usr/bin/vim /root/.bashrc使用 vim 编辑器打开 root 用户的 .bashrc 配置文件。 export PATH/root:$PATH将 /root 目录添加到 PATH 环境变量的最前面。 esc -- :wq在 vim 中按 Esc 退出编辑模式输入 :wq 保存并退出。 source /root/.bashrc使 .bashrc 的修改立即生效。 1.sh执行名为 1.sh 的脚本文件假设该脚本已设置可执行权限。
PS:删除用rm或者编辑的方式删除变量 四、字符串操作
在编程中字符串操作是非常常见且重要的任务之一。无论是在文本处理、文件解析还是在网络数据处理等场景中我们都需要灵活地操作和处理字符串。尤其在 Shell 脚本 中字符串操作不仅是脚本功能的基础而且直接影响脚本的可读性和效率。
1. 字符串拼接
在 Shell 中字符串拼接非常简单可以直接通过空格来连接字符串
str1Hello
str2World
result$str1 $str2 # 拼接后 Hello World
echo $result 2.字符串切片
在 Shell 中字符串切片使用 ${string:start:length} 语法
textHello, World!
slice${text:0:5} # 获取 Hello
echo $slice
如果你想从某个位置切到结尾可以这样做
slice${text:7} # 从位置 7 开始获取 World!
echo $slice 3. 字符串查找
在 Shell 中可以使用 grep 或 [[ ]] 来判断子字符串是否存在 使用 [[ ]] 判断子字符串是否存在 textHello, World!
if [[ $text *World* ]]; thenecho Found World
fi 使用 grep 查找字符串 textHello, World!
echo $text | grep -q World # 如果找到 World返回 0
if [[ $? -eq 0 ]]; thenecho Found World
fi
4. 字符串替换
Shell 也可以进行简单的字符串替换 替换第一次出现的子字符串 textHello, World!
result${text/World/Python} # 替换第一个 World 为 Python
echo $result # 输出 Hello, Python! 替换所有出现的子字符串 textHello, World! Hello again!
result${text//Hello/Hi} # 替换所有 Hello 为 Hi
echo $result # 输出 Hi, World! Hi again! 5. 字符串大小写转换
Shell 原生不直接支持大小写转换但可以借助 tr 或 awk 等工具来实现 转为大写 texthello
result$(echo $text | tr a-z A-Z) # 转为大写
echo $result # 输出 HELLO 转为小写 textHELLO
result$(echo $text | tr A-Z a-z) # 转为小写
echo $result # 输出 hello 6. 字符串分割
在 Shell 中字符串分割通常是通过设置 IFS内部字段分隔符来实现的
textapple,banana,orange
IFS, read -ra fruits $text
# 现在数组 fruits 存储了 [apple, banana, orange]
for fruit in ${fruits[]}; doecho $fruit
done 7. 去除空白 去除首尾空白字符使用 sed 或 awk text Hello, World!
result$(echo $text | sed s/^[[:space:]]*//;s/[[:space:]]*$//) # 去除首尾空白
echo $result # 输出 Hello, World! 去除中间的空白字符 text Hello World
result$(echo $text | tr -s ) # 压缩多个空格为一个
echo $result # 输出 Hello World
8. 字符串长度
可以使用 ${#string} 来获取字符串的长度
textHello, World!
length${#text} # 获取字符串长度
echo $length # 输出 13 9. 其他常见字符串操作 字符串反转 Shell 本身没有内建的字符串反转函数但可以用 rev 命令来反转字符串 textHello
result$(echo $text | rev) # 使用 rev 命令反转字符串
echo $result # 输出 olleH 检查是否为数字 text12345
if [[ $text ~ ^[0-9]$ ]]; thenecho Its a number
elseecho Its not a number
fi
这些是 Shell 脚本中常见的字符串操作方法。在实际使用时你可以根据需求选择合适的命令和语法。对于更复杂的字符串操作可以考虑使用外部工具如 awk、sed、cut 等。 五、数值的运算
在 Shell 脚本中数值运算是非常基础且常用的操作之一。无论是在处理数据、计算结果还是在自动化脚本中进行逻辑判断数值运算都是不可或缺的一部分。为了满足不同的计算需求Shell 提供了多种运算方式如使用常见运算符、$(())、let 命令和 expr 工具进行运算。
1. 常见运算符
以下是常见的数学运算符及其用途
运算符说明示例加法a b-减法a - b*乘法a * b/除法a / b%取余a % b**幂运算a ** b 2.使用 $(( )) 进行算术运算
$(( )) 是最常见的算术运算方式它支持加法、减法、乘法、除法、取余、幂运算等。例子
#!/bin/bash
# 加法
a5
b3
result$((a b))
echo $a $b $result
# 减法
result$((a - b))
echo $a - $b $result
# 乘法
result$((a * b))
echo $a * $b $result
# 除法
result$((a / b))
echo $a / $b $result
# 取余
result$((a % b))
echo $a % $b $result
# 幂运算 (注意bash 4 支持)
a2
result$((a ** 3))
echo $a^3 $result 3. 使用 let命令进行算术运算
let 命令是另一种进行算术运算的方式它支持与 $(( )) 类似的操作。使用 let 时运算结果存储在变量中不需要额外的赋值符号。
#!/bin/bash
a5
b3
# 加法
let resultab
echo $a $b $result
# 乘法
let resulta*b
echo $a * $b $result 4. 使用expr进行算术运算
expr 是一个外部命令支持基础的算术运算但要求参数之间要有空格。在脚本中使用时通常需要加上反引号, 用于命令替换或者$()。
#!/bin/bash
a5
b3
# 加法
result$(expr $a $b)
echo $a $b $result
# 乘法
result$(expr $a \* $b)
echo $a * $b $result
注意在使用 expr 时运算符如 * 必须转义加上反斜杠 \否则会被 shell 解释为通配符。 5. 浮点数运算
Shell 默认只支持整数运算如果要进行浮点数运算可以使用 bcBasic Calculator命令。bc 是一个支持浮点数运算的工具。
#!/bin/bash
a5
b3
# 浮点除法
result$(echo scale2; $a / $b | bc)
echo $a / $b $result
# 浮点加法
result$(echo $a $b | bc)
echo $a $b $result scale2设置结果的小数位数这里是保留两位小数。 echo | bc通过管道将表达式传递给 bc 执行计算。 6. 数学运算赋值给变量 $(( )) 是最常用且推荐的方式直接支持赋值给变量。 let 可以直接将计算结果赋值给变量但它不支持括号或复杂表达式。 expr 需要将计算结果通过命令替换 ($( )) 赋值给变量且运算符如 * 必须加上反斜杠进行转义。
6.1. 使用 $(( )) 进行运算并赋值
#!/bin/bash
a5
b3
# 将计算结果赋值给变量
result$((a b)) # 加法
echo Result of a b: $result
result$((a - b)) # 减法
echo Result of a - b: $result
result$((a * b)) # 乘法
echo Result of a * b: $result
result$((a / b)) # 除法
echo Result of a / b: $result
result$((a % b)) # 取余
echo Result of a % b: $result
6.2. 使用 let 进行运算并赋值
#!/bin/bash
a5
b3
# let 会直接修改变量值
let resultab # 加法
echo Result of a b: $result
let resulta-b # 减法
echo Result of a - b: $result
let resulta*b # 乘法
echo Result of a * b: $result
let resulta/b # 除法
echo Result of a / b: $result
let resulta%b # 取余
echo Result of a % b: $result
6.3. 使用 expr 进行运算并赋值
#!/bin/bash
a5
b3
# expr 命令计算并赋值给变量
result$(expr $a $b) # 加法
echo Result of a b: $result
result$(expr $a - $b) # 减法
echo Result of a - b: $result
result$(expr $a \* $b) # 乘法
echo Result of a * b: $result
result$(expr $a / $b) # 除法
echo Result of a / b: $result
result$(expr $a % $b) # 取余
echo Result of a % b: $result 7. 使用 let和 $(( ))的区别 let 是一种命令而 $(( )) 是一种算术扩展通常 $(( )) 更为灵活推荐使用。 let 只能处理整数运算。 $(( )) 更加简洁且支持较为复杂的数学表达式。 8. 数值运算段落小结 $(( )) 是进行算术运算的最常见方法支持加法、减法、乘法、除法、取余、幂运算等。 let 命令也支持算术运算但更适合简单的场合。 expr 命令是一个外部工具虽然可以进行算术运算但使用时要注意空格和转义符。 对于浮点数运算bc 是必不可少的工具。
通过这些方法你可以在 Shell 脚本中进行各种数学运算处理整数和浮点数数据。 六、脚本与用户交互
在 Shell 脚本中与用户的交互是实现动态输入和灵活操作的重要手段。通过命令行参数传递和 read 命令我们可以让脚本根据不同的输入做出相应的处理。
1.命令行参数传递
1.1.获取的特殊变量
在 Shell 脚本中参数传递是通过特殊变量来完成的以下是几个常用的参数变量 $0脚本本身的名字。 $1, $2, $3, ...脚本传递的第一个、第二个、第三个等参数。 $#传递给脚本的参数个数。 $所有传递给脚本的参数作为一个单独的字符串。 $*与 $ 类似表示所有参数但 $ 会保留参数的单独性而 $* 将所有参数当作一个字符串来处理。 $?上一个命令的退出状态返回值。 $$脚本的进程 ID
1.2.示例
echo 执行的文件名是$0
echo 第一个参数是$1
echo 第一个参数是$2
echo 第一个参数是$3
echo 传递的参数作为一个字符串显示$*
echo 传递的参数独立作为每个字符串显示$
echo 传递到脚本的参数个数是$#
echo 最后命令的退出状态$?
echo 脚本运行的当前进程ID是$$ 在 Bash 脚本中参数的传递允许我们根据命令行输入动态地处理数据。脚本通过位置参数如 $1, $2, $3 等获取用户传递的值这些值可以是任意文本或数值。如果没有传递参数脚本会处理为空的值。 特殊变量 $* 和 $ 则用于获取所有传递的参数分别作为一个整体字符串或独立的字符串处理。 $# 用来获取传递参数的个数而 $? 显示最后执行命令的退出状态$$ 提供当前脚本的进程 ID。 这些参数和变量帮助我们在脚本中处理不同的输入增强脚本的灵活性和功能。 2. read命令交互
在Shell脚本中与用户进行交互时主要使用的是 read 命令来接收用户输入read 命令用于从标准输入通常是键盘读取一行数据并将其赋值给指定的变量。它是实现用户输入交互的主要工具。
2.1.基本语法
read [options] variable_name variable_name输入的数据将存储到此变量中。 options一些额外的选项用来定制输入行为。
2.2.常用参数和选项 1.2.1. -p打印提示信息 read -p 请输入您的名字: name
echo 您好$name! 该选项允许在接收输入之前输出提示信息提示信息会直接显示在输入框之前。 在上面的例子中-p 选项让用户看到“请输入您的名字”提示信息然后输入名字。用户输入的内容会被存储在 name 变量中。 1.2.2. -s隐藏输入 -s 选项用于隐藏用户输入的内容常用于密码输入等场合。 read -s -p 请输入密码: password
echo 密码已输入,您刚才输入的密码是$password 这里用户输入的内容会被隐藏不显示在屏幕上但仍然可以存储在 password 变量中。 1.2.3. -n限定输入字符数 -n 选项指定用户输入的字符数。当用户输入指定数量的字符后read 会立即停止输入不会等待回车。 read -n 4 -p 请输入手机号后四位: input
echo 您输入的是: $input 在上面的例子中用户只能输入4个字符输入后会立即显示结果。 1.2.4. -t设置超时限制 -t 选项允许设置输入超时。如果用户在指定时间内没有输入read 会自动退出并返回非零的退出状态。 read -t 10 -p 请输入您的名字 (10秒内): name
if [ $? -eq 0 ]; thenecho 您好$name!
elseecho 输入超时
fi 在这个例子中用户必须在10秒内输入。如果时间超时没有输入会显示“输入超时”。 1.2.5. -a读取为数组 -a 选项允许用户输入多个值并将这些值保存到一个数组中。用户输入的每个单词由空格分隔都会被当作数组元素。 read -a colors -p 请输入几种颜色用空格分隔:
echo 您输入的颜色是: ${colors[]} 在这个例子中用户输入的多个颜色将被存储为数组 colors并通过 ${colors[]} 打印出来。 1.2.6. -e启用编辑模式 -e 选项允许启用输入的编辑模式使得用户可以使用箭头键来编辑输入内容。这通常在交互式脚本中非常有用但需要在支持编辑模式的环境中使用。 read -e -p 请输入一个命令: command
echo 您输入的命令是: $command 启用 -e 后用户可以使用键盘上的左右箭头、删除键等编辑输入内容。 2.3.使用多个变量
read 命令可以一次读取多个变量用户输入的每个空格分隔的值会被依次赋值给指定的变量。
read var1 var2 var3
echo var1$var1, var2$var2, var3$var3
如果用户输入了多个值read 会将每个值分配给相应的变量。如果输入的值少于变量的个数未赋值的变量会被设置为默认值通常是空字符串。 七、if 条件判断
在 Bash 脚本中if 语句用于根据某个条件是否为真来决定是否执行特定的代码块。
1.基本语法
if [ 条件 ]
then# 如果条件为真执行的命令
else# 如果条件为假执行的命令可选
fi [ 条件 ] 是测试条件的部分。[ ] 是 test 命令的简写表示判断某个条件。 then 后面是条件成立时执行的代码块。 else 是可选的表示条件不成立时执行的代码块。 fi 是 if 语句的结束标志。
PS[ 条件 ]可以用test来代替但是不推荐用格式if test 条件 ; 2.多条件判断语法
2.1if-elif-else 语句
如果有多个条件需要判断可以使用 elif 来扩展条件判断。
if [ $age -ge 18 ]
thenecho You are an adult.
elif [ $age -ge 13 ]
thenecho You are a teenager.
elseecho You are a child.
fi
输出 根据 $age 的值输出对应的年龄段信息。 if 用于检查单个条件。 if-else 用于条件成立时和不成立时分别执行不同的操作。 if-elif-else 用于多个条件判断。 3. 关系运算符
在 Bash 中关系运算符用于比较数值、字符串等。常用的关系运算符如下
3.1. 数值比较运算符
运算符说明示例-eq等于if [ $a -eq $b ]; then-ne不等于if [ $a -ne $b ]; then-gt大于if [ $a -gt $b ]; then-lt小于if [ $a -lt $b ]; then-ge大于或等于if [ $a -ge $b ]; then-le小于或等于if [ $a -le $b ]; then
3.1.2. 示例数值比较
#!/bin/bash
read -p 请输入一个数字 num
if [ $num -gt 10 ]; thenecho 输入的数字大于 10
elif [ $num -eq 10 ]; thenecho 输入的数字等于 10
elseecho 输入的数字小于 10
fi 3.2. 字符串比较运算符
运算符说明示例等于if [ $a $b ]; then!不等于if [ $a ! $b ]; then小于字典序比较if [[ $a $b ]]; then大于字典序比较if [[ $a $b ]]; then-z字符串为空if [ -z $a ]; then-n字符串非空if [ -n $a ]; then
3.2.1.示例字符串比较
#!/bin/bash
read -p 请输入你的名字 name
if [ $name Alice ]; thenecho 你好Alice
elseecho 你好$name我找Alice
fi 4. 逻辑运算符
Bash 中可以使用逻辑运算符来连接多个条件判断。
4.1. 常用逻辑运算符 与运算符AND只有当左边和右边的条件都为真时整个表达式才为真。 ||或运算符OR只要左边或右边有一个条件为真整个表达式为真。 !非运算符NOT将条件反转。
4.1.1. 示例逻辑与AND运算符
#!/bin/bash
echo 请输入两个数字
read num1 num2 #使用多个变量输入
if [ $num1 -gt 10 ] [ $num2 -lt 20 ]; thenecho 第一个数字大于 10 且第二个数字小于 20
elseecho 条件不成立
fi
4.1.3. 示例逻辑或OR运算符
#!/bin/bash
echo 请输入两个数字
read num1 num2 #使用多个变量输入
if [ $num1 -gt 10 ] || [ $num2 -lt 20 ]; thenecho 至少有一个条件成立
elseecho 两个条件都不成立
fi
4.1.4.示例逻辑非!运算符
逻辑非运算符!是布尔值逻辑中非常常见且有用的操作符用于取反表达式的值。在多种编程语言中! 的使用方式是类似的通常用来反转布尔条件或进行短路逻辑判断。
if ! 条件表达式
then# 当条件表达式为假时执行的代码
fi
4.1.4.1.判断一个文件是否不存在。
#!/bin/bash
FILEtestfile.txt
# 使用 ! 运算符判断文件是否不存在
if ! [ -f $FILE ]; thenecho 文件 $FILE 不存在
elseecho 文件 $FILE 已存在
fi ! 运算符用于取反 [ -f $FILE ] 的结果。如果文件 testfile.txt 不存在那么 [ -f $FILE ] 为假返回非零使用 ! 后变为真返回0进入 if 语句的条件分支输出 文件 testfile.txt 不存在。 如果文件存在[ -f $FILE ] 为真返回0! 后变为假程序执行 else 部分输出 文件 testfile.txt 已存在。
4.1.4.2.判断命令执行是否失败
#!/bin/bash
# 尝试执行一个命令
if ! ls /nonexistent_directory; thenecho 目录不存在命令执行失败
elseecho 目录存在命令执行成功
fi ! ls /nonexistent_directory 是对 ls /nonexistent_directory 命令的取反操作。由于目录 /nonexistent_directory 不存在ls 命令会失败并返回非零值这时逻辑非运算符 ! 会将其反转为成功的状态返回0从而进入 if 语句中的代码块输出 目录不存在命令执行失败。 5. if 语句的结合 read和参数传递
可以通过将 read 命令与传递的脚本参数相结合在脚本中创建交互式的输入或根据参数进行判断。
5.1. 示例if判断结合read完成登录校验功能
假设我们有一个脚本它通过 read 获取的输入做出不同的响应。 首先提示用户输入用户名。 如果用户名为空则提示用户输入不能为空。 如果用户名不为空则继续提示用户输入密码。 最后通过 if 判断用户名和密码是否符合预定条件用户名为 admin 和密码为 1234。
#!/bin/bash
# 提示用户输入用户名
read -p 请输入用户名 username
# 判断用户名是否为空
if [ -z $username ]; thenecho 用户名不能为空
else# 提示用户输入密码read -s -p 请输入密码 password
# 假设用户名为 admin 和密码为 1234 才为有效if [ $username admin ] [ $password 1234 ]; thenecho 登录成功elseecho 用户名或密码错误。fi
fi
5.2. 示例根据参数判断并结合 read
假设我们有一个脚本它根据用户输入的参数或通过 read 获取的输入做出不同的响应。 使用 if [ $# -gt 0 ] 判断脚本是否接收到命令行参数。如果接收到参数则使用 input\$1 来将第一个参数赋值给 input。 如果没有传入参数脚本会使用 read 命令要求用户输入一个数字。 最后使用 if 判断输入的数字是否大于 10并输出相应的信息。
#!/bin/bash
# 判断是否有传入参数
if [ $# -gt 0 ]; then# 如果有传入参数则使用第一个参数input\$1
else# 如果没有传入参数使用 read 命令从用户获取输入read -p 请输入一个数字 input
fi
# 判断输入的数字
if [ $input -gt 10 ]; thenecho 输入的数字大于 10
elseecho 输入的数字小于或等于 10
fi 6. if条件判断段落小结 if 语句用于根据条件执行不同的命令。可以结合数值、字符串比较以及逻辑运算符AND、OR、NOT来构建复杂的条件判断。 关系运算符用于数值和字符串的比较常见的包括 -eq, -ne, -gt, -lt, -ge, -le 等。 逻辑运算符用于连接多个条件判断如 与、||或和 !非。 read 与参数传递结合通过脚本参数和 read 的结合可以实现更加灵活的输入方式既可以通过命令行传递参数也可以通过 read 进行交互式输入。
这些基本的条件判断和逻辑运算符是 Bash 脚本中非常重要的组成部分掌握它们能让你编写更加智能和灵活的脚本。 八、循环
1. for 循环
for 循环是一种用于遍历列表可以是数字范围、文件列表或命令输出等的控制结构。它重复执行命令直到列表中的所有元素都被处理完。
1.1.for循环语法
for var in list
do# 执行的命令
done var 是循环变量依次从 list 中获取值。 list 可以是一个数字范围、字符串列表或命令输出等。 1.2.示例遍历数字列表
for i in 1 2 3 4 5
doecho Number: $i
done
在这个例子中for 循环会依次将数字 1 到 5 赋给变量 i然后执行 echo 命令。 1.3.示例使用命令输出作为列表
for file in $(ls /etc)
doecho File: $file
done
输出 列出 /etc 目录中的所有文件或子目录。 已知需要遍历的元素如数字、文件、命令输出等。 当循环次数是预先确定的。 2. while 循环
while 循环会根据指定的条件判断在条件为真时不断重复执行指定的命令。它适用于当你不确定循环的具体次数但需要根据某个条件来决定是否继续循环。
2.1. while 循环语法
while condition
do# 执行的命令
done condition循环的条件只要条件返回 true循环就会继续执行。 commands条件为真时要执行的命令。
2.2.示例计数循环
i1
while [ $i 5 ]
doecho Number: $ii$((i 1)) # 递增 i
done
在这个例子中while 循环会检查 i 是否小于或等于 5只要条件成立就执行 echo 命令并增加 i 的值。如果为假则中断循环。
2.3.示例直到某个条件满足为止
while ! curl -s http://example.com /dev/null
doecho Waiting for website to be up...sleep 5
done
这个例子在网站不可达时会每 5 秒重试一次直到网站可用为止。 3. until 循环
until 循环的语法类似于 while 循环但它的条件是 当条件为假时循环会继续执行。可以理解为 while 循环的条件是 为真时而 until 则相反条件为假时执行。
语法
until [ 条件 ]
do# 循环体
done
例子
例子
#!/bin/bash
count1
until [ $count -gt 10 ] # 直到 count 大于 5 时退出
doecho Count is: $count((count)) # 增加 count
done
3.1.代码功能概述 until 循环只有在循环条件为 真 时才退出。这里的条件是 count -gt 10当 count 达到 11 时条件成立循环停止。 通过 count每次循环结束后count 会递增 1直到达到退出条件。
3.2.循环条件分析 until [ $count -gt 10 ]: until 循环会一直执行直到指定的条件为 真。 在这个例子中条件是 [ $count -gt 10 ]表示当 count 大于 10 时条件为真。 只有当 count 大于 10 时until 循环才会停止执行。
3.3.执行过程 初始时count1。 循环开始时检查条件 [ $count -gt 10 ]。由于 count 初始为 1条件 1 -gt 10 为假因此继续执行循环体。 输出当前 count 的值Count is: 1。 然后 count 增加 1count 变为 2。 再次检查条件 [ $count -gt 10 ]此时 count 为 2条件 2 -gt 10 仍为假继续执行循环。 依此类推直到 count 增加到 11。 当 count 为11 时检查条件 [ $count -gt 10 ]此时条件为真循环退出。 4.case 语句
case 语句用于多重条件匹配它根据变量的值与多个模式进行比较执行匹配成功的块类似于其他语言中的 switch 语句。
语法
case $变量 in模式1)# 当变量匹配模式1时执行;;模式2)# 当变量匹配模式2时执行;;*)# 默认情况;;
esac
例子
#!/bin/bash
read -p 请输入一个数字 num
case $num in1)echo 你输入的是数字 1;;2)echo 你输入的是数字 2;;3)echo 你输入的是数字 3;;*)echo 输入的数字不在预期范围内;;
esac
4.1.代码功能概述
该脚本使用 case 语句根据用户输入的数字输出不同的提示信息。用户输入的数字将与预设的 1、2、3 进行匹配。如果输入的数字是其中之一则输出相应的消息如果输入的数字不在预期的范围内即不等于 1、2、3则输出默认的提示消息。
4.2.循环条件分析
虽然这段脚本中没有使用显式的 循环例如 for 或 while 循环但它依然有条件判断逻辑。具体来说case 语句会根据用户输入的数字值执行不同的分支类似于条件分支的“匹配”过程。
具体流程 用户通过 read -p 提示输入一个数字将该数字存储在变量 num 中。 case语句根据num的值执行以下匹配 如果用户输入的是 1输出 你输入的是数字 1。 如果用户输入的是 2输出 你输入的是数字 2。 如果用户输入的是 3输出 你输入的是数字 3。 如果用户输入的是其他数字或字符与预设的 1、2、3 都不匹配则会执行默认分支输出 输入的数字不在预期范围内。 5.总结对比
结构语法特点适用场景for 循环遍历列表中的元素已知元素列表或循环次数while 循环条件为真时继续执行条件判断后执行直到条件不再满足until 循环条件为假时继续执行直到某条件满足才停止case 语句基于匹配的值进行条件判断替代多个 if-else 分支类似于其他语言中的 switch 语句。 九、函数
在Shell脚本中函数function是用来组织和封装代码块的一种方式它能够帮助你提高代码的可读性和可重用性。我们可以将多次需要执行的命令、语句块或逻辑封装成一个函数调用时只需提供函数名Shell会自动执行对应的代码。 Shell函数的参数可以通过 $1, $2, $, $# 等方式访问。 使用 local 关键字定义局部变量避免变量污染。 函数的返回值通常通过 echo 输出而 return 语句通常用于返回状态码。 使用 shift 可以处理函数中的多参数递归也可以在Shell函数中实现。
1. 函数的定义与使用
在Shell脚本中函数是通过 function 关键字或直接使用函数名来定义的。可以通过 () 定义函数也可以通过 return 语句返回函数的结果。
语法
# 定义函数
function my_function {# 函数体
}
# 或者可以直接使用下面的方式
my_function() {# 函数体
}
两者是等价的选择哪种方式主要取决于个人或团队的代码风格。传统方式比较简洁而带 function 关键字的方式可能显得更直观特别是当函数非常复杂时。
例子
#!/bin/bash
# 定义一个简单的函数
greet() {echo Hello, $1! # $1 是传入的第一个参数
}
# 调用函数
greet tom
greet 你见过龙吗 2. 函数的传参
Shell函数可以接收外部传递的参数函数的参数是通过 $1、$2、$3 、$0、$、$#等位置变量来访问的这些变量代表了传递给函数的参数。 $1, $2, $3 分别代表了传入参数的第一个、第二个、第三个位置。 $0 表示脚本本身的名称。 $表示传递给函数的所有参数作为一个单独的字符串数组来处理。 $#表示传递给函数的参数个数。
例子
#!/bin/bash
# 定义一个函数计算两个数的和
sum() {local num1$1 # 第一个参数local num2$2 # 第二个参数echo Sum is: $((num1 num2))
}
# 调用函数传递两个参数
sum 5 7
sum 10 20 3. 局部变量local
在Shell脚本中默认情况下所有变量的作用范围是全局的这意味着如果在一个函数内部修改了一个变量的值它将影响到函数外部的相同变量。如果我们想在函数内部定义一个仅在该函数范围内有效的变量可以使用 local 关键字。
#!/bin/bash
my_function() {local varlocal_variableecho Inside function: $var
}
# 在函数外部访问同名变量
varglobal_variable
my_function
echo Outside function: $var
可以看到local 关键字确保了 var 变量仅在 my_function 内部有效函数外部的 var 变量没有受到影响。
3.1.为什么使用 local 避免命名冲突当一个脚本中有多个函数时如果多个函数使用相同的变量名而没有使用 local它们可能会相互覆盖造成意外的结果。使用 local 可以有效避免这种情况。 封装性使用 local 可以将变量的作用域限制在函数内部提升代码的可维护性和可读性。 4. 函数返回值
Shell函数默认没有返回值但你可以使用 return 语句返回一个整数值。需要注意的是return 语句只能返回 0 到 255 之间的整数通常用于表示状态码。
例子
#!/bin/bash
# 定义一个函数检查文件是否存在
check_file() {if [ -f $1 ]; thenreturn 0 # 文件存在elsereturn 1 # 文件不存在fi
}
# 调用函数并检查返回值
check_file /etc/passwd
if [ $? -eq 0 ]; thenecho 文件存在
elseecho 文件不存在
fi 5. 函数中的递归调用
Shell支持函数的递归调用也就是函数在自身内部调用自身。递归调用通常需要一个基准条件来防止无限递归。
递归示例计算阶乘
#!/bin/bash
factorial() {if [ $1 -le 1 ]; thenecho 1elselocal result$(( $1 * $(factorial $(( $1 - 1 )) ) ))echo $resultfi
}
result$(factorial 5)
echo Factorial of 5 is: $result 6. 内建函数与外部函数的区别 内建函数Shell本身内置的命令和函数例如 echo, read, test, pwd 等这些函数不需要额外定义Shell会直接识别。 外部函数通过 Shell 脚本或程序中定义的函数。这些函数是用户自定义的不是Shell内建的。 十、不同脚本的互相调用
Shell 脚本可以通过几种方式调用其他脚本或命令
1.直接调用
我们可以直接在一个脚本中调用另一个脚本方法是提供脚本路径或脚本名称。如果另一个脚本在当前目录下并且有执行权限可以直接调用。
#initiate.sh
echo Hello,world
#other_script.sh
# 调用其他脚本
./initiate.sh
但是这种方式是需要initiate.sh拥有被执行权限的。 2.使用 source 或 . 命令
source 命令或者 .点命令可以在当前 Shell 环境中执行另一个脚本而不会启动一个新的子进程。这意味着如果被调用的脚本修改了环境变量或其他设置这些修改会影响当前脚本。
#initiate.sh
nameTom
age18
#other_script.sh
# 使用 source 或 . 来执行脚本
source initiate.sh
echo Hello, my name is $name and I am $age years old
# 或者
. initiate.sh
echo Hello, my name is $name and I am $age years old
这种方式通常用于共享函数、变量或环境设置等。 3.使用 bash 命令调用
我们也可以通过 bash 命令调用另一个脚本并启动一个新的子 Shell 来执行脚本。
#initiate.sh
echo Hello,world
#other_script.sh
bash initiate.sh # 调用其他脚本
这种方式和直接调用的区别是不需要执行权限直接通过bash解释器来调用sh脚本。 4.传递参数给脚本
在调用其他脚本时可以传递参数接收脚本中的 $1, $2, … 等位置参数。
#initiate.sh
echo Hello, my name is $1 and I am $2 years old
#other_script.sh
bash initiate.sh ikun 2.5
在 initiate.sh 中可以通过 $1, $2 等获取传递的参数。 十一、重定向操作
1.输出重定向
将命令的标准输出重定向到指定的文件中。如果文件存在重定向会覆盖文件内容如果文件不存在则会创建该文件。
echo Hello, World! output.txt
cat output.txt
ls output.txt
cat output.txt 2.追加输出
将命令的标准输出追加到指定文件的末尾而不会覆盖文件原有内容。
echo Hello output.txt
echo My name is ikun and I am 2.5 years old output.txt
cat output.txt 3.输入重定向
将文件的内容作为命令的输入。例如可以通过重定向从文件中读取输入而不需要通过标准输入。
sort output.txt
cat output.txt 4.错误输出重定向2
将标准错误stderr输出重定向到文件中。标准错误通常用于显示错误信息。
ikun 2 error.log
cat error.log 5.同时重定向标准输出和标准错误
有时我们需要将标准输出和标准错误都重定向到同一个文件。可以通过以下方式
ikun output.txt 21
ls output.txt 21
cat output.txt
这将同时将标准输出和标准错误输出重定向到 output.txt 文件中。 6.文件描述符介绍
在 Shell 脚本中文件描述符 是对输入输出流的抽象。Shell 默认有三个文件描述符 标准输入stdin文件描述符 0通常用于接收来自键盘或文件的输入。 标准输出stdout文件描述符 1通常用于输出到终端或文件。 标准错误stderr文件描述符 2通常用于输出错误信息。
文件描述符使得我们能够灵活控制输入输出流。可以通过以下方式进行更复杂的输入输出操作
6.1.重定向文件描述符
通过重定向文件描述符可以将标准输入、输出或错误输出指向其他文件或设备。 将标准输出重定向到文件 echo This is an info message output.txt 将标准错误输出重定向到文件 ikun 2 error.log 同时将标准输出和标准错误输出重定向到同一个文件 ikun output.log 21
6.2.使用 exec 进行更复杂的重定向
exec 命令可以在脚本中为特定文件描述符分配新的文件。
例如以下命令会将文件描述符 3 重定向到文件 myfile.log
exec 3 myfile.log
echo This goes to myfile.log 3
关闭文件描述符如果不再需要某个文件描述符可以使用 exec 来关闭它。
exec 3- 结语 通过本系列的学习我们深入探讨了 Shell脚本 的各个核心概念和常用技巧。从基本的 变量定义、条件判断、循环结构到更复杂的 脚本参数传递、数学运算 和 脚本间调用每一部分都为我们编写高效、简洁的脚本打下了坚实的基础。 在这段学习旅程中我们掌握了如何使用 if 条件判断 来控制程序的执行流程如何通过 for、while 和 until 等循环结构来处理重复任务还了解了 case 语句 和 函数 的灵活应用。此外掌握了 字符串操作 和 环境变量管理使得我们能够更好地与系统进行交互并编写出更具有可维护性和可扩展性的脚本。 Shell脚本不仅是系统管理员、DevOps 工程师和开发人员日常工作的重要工具它还帮助我们简化了复杂的任务自动化了很多重复性操作提高了工作效率。 脚本语言的魅力在于其简洁与强大而 Shell 脚本更是 Unix/Linux 系统中的重要组成部分。无论是处理文件操作、自动化备份、配置系统还是进行日志分析和任务调度Shell 脚本都能够为我们的工作带来巨大的便利。 通过本系列的学习相信大家已经具备了编写、调试和优化 Shell 脚本的能力。希望你们能够将这些知识应用到实际的工作中不断提高脚本的质量与效率探索更多自动化和高效工作的可能性。 最后Shell脚本学习之路没有尽头技术的深度和广度总是值得我们不断探索和进步。祝愿大家在今后的脚本编写过程中能够不断突破自己遇见更多挑战与机遇。 往期文章
shell脚本_创建执行与变量的定义与使用-CSDN博客
shell脚本_永久环境变量和字符串操作和shell如何变成永久变量-CSDN博客
shell脚本_脚本参数传递与数学运算-CSDN博客
shell脚本_脚本与用户交互以及if条件判断-CSDN博客
shell脚本_if条件判断与for循环结构讲解与示例-CSDN博客
shell脚本_for循环与while循环讲解和对比-CSDN博客
shell脚本_until循环和case语句与函数的定义和使用-CSDN博客
shell脚本_不同脚本的互相调用和重定向操作-CSDN博客