当前位置: 首页 > news >正文

linux入门六:Linux Shell 编程

一、Shell 概述

1. 什么是 Shell?

Shell 是 Linux 系统中用户与内核之间的桥梁,作为 命令解析器,它负责将用户输入的文本命令转换为计算机可执行的机器指令。

  • 本质:Shell 是一个程序(如常见的 Bash、Zsh),而 Shell 脚本则是包含一系列命令的文本文件,通常以 .sh 结尾(非强制,仅为识别方便)。
  • 作用:批量执行重复命令、实现自动化任务、编写复杂逻辑程序。

2. 为什么选择 Bash?

  • 主流性:Bash(Bourne Again Shell)是 Linux 系统的默认 Shell,几乎所有发行版都内置,兼容性强。
  • 功能强大:支持变量、数组、函数、流程控制等高级特性,满足从简单脚本到复杂程序的需求。
  • 学习门槛低:语法简洁,对新手友好,且与早期 Shell(如 Bourne Shell)兼容。

二、Shell 脚本基础操作

1. 脚本文件的创建与编辑

1.1 选择文本编辑器

Shell 脚本本质是纯文本文件,推荐使用以下编辑器:

  • nano(新手友好):命令行下的简单编辑器,通过 nano 文件名 启动,支持鼠标和快捷键操作。
  • vim(功能强大):通过 vim 文件名 启动,需切换模式(i 进入插入模式,Esc 退出,:wq 保存并退出)。
  • gedit(图形界面):适合桌面环境,直接右键文件选择「用文本编辑器打开」。
1.2 创建脚本文件
# 在当前目录创建名为 demo.sh 的脚本文件
touch demo.sh
1.3 编写脚本内容
# 用 nano 打开并编辑脚本
nano demo.sh

输入以下内容:

#!/bin/bash
# 这是一个简单的 Shell 脚本示例
echo "Hello, World!"  # 输出文本

关键行解释

  • #!/bin/bash:指定脚本使用 Bash 解释器执行,必须位于文件第一行。
  • # 开头的行是注释,用于解释代码逻辑,不参与执行。
  • echo 命令用于输出文本,默认换行。若需不换行,使用 echo -n "内容"

2. 脚本的执行方式

2.1 方式一:通过 bash 命令执行(无需权限)
bash demo.sh

原理:直接调用 Bash 解释器执行脚本,适用于快速测试,无需修改文件权限。

2.2 方式二:通过 sh 命令执行(兼容旧版)
sh demo.sh

注意sh 通常指向 Bash,但某些系统中可能指向更古老的 Shell(如 BusyBox sh),可能导致兼容性问题。建议统一使用 #!/bin/bash 头部。

2.3 方式三:赋予执行权限后运行(推荐)
# 赋予文件执行权限
chmod +x demo.sh
# 通过相对路径执行
./demo.sh

关键点

  • chmod +x 用于添加执行权限,否则会提示 Permission denied
  • ./ 表示当前目录,必须显式指定路径,因为当前目录默认不在系统 PATH 中。

3. 脚本执行的常见问题与解决

3.1 权限不足

错误提示Permission denied
解决方法

chmod +x demo.sh  # 赋予执行权限
3.2 路径错误

错误提示No such file or directory
可能原因

  1. 脚本路径错误(如 ./demo.sh 写成 demo.sh)。
  2. 脚本文件格式问题(如 Windows 换行符导致的错误)。
    解决方法
# 检查路径是否正确
ls -l demo.sh  # 确认文件存在且路径正确# 转换文件格式为 Unix 格式(若文件来自 Windows)
dos2unix demo.sh  # 需先安装 dos2unix 工具
3.3 解释器路径错误

错误提示Bad interpreter: No such file or directory
可能原因:脚本头部 #!/bin/bash 路径错误。
解决方法

# 查看系统 Bash 路径
which bash  # 通常输出 /bin/bash# 修改脚本头部为正确路径
vim demo.sh  # 将第一行改为 #!/usr/bin/env bash(更具可移植性)

4. 脚本调试与验证

4.1 检查执行结果
# 执行脚本并查看输出
./demo.sh  # 正常输出:Hello, World!# 检查命令执行状态(0 表示成功)
echo $?  # 输出:0
4.2 调试模式
# 启用调试模式,显示每行执行的命令
bash -x demo.sh
4.3 错误处理
# 脚本遇到错误时立即退出
set -e# 捕获错误并输出信息
trap 'echo "错误发生在第 $LINENO 行"' ERR

5. 脚本优化与进阶

5.1 输出重定向
# 将输出保存到文件(覆盖原有内容)
./demo.sh > output.log# 追加输出到文件
./demo.sh >> output.log
5.2 输入重定向
# 从文件读取输入
cat input.txt | ./demo.sh
5.3 环境变量与脚本交互
# 在脚本中引用环境变量
echo "当前用户:$USER,主目录:$HOME"# 导出自定义变量到子进程
export MY_VAR="自定义变量"

6. 实战案例:批量创建用户

#!/bin/bash
# 批量创建用户脚本# 定义用户列表
users=("user1" "user2" "user3")# 遍历用户列表并创建用户
for user in ${users[@]}; douseradd $user && echo "用户 $user 创建成功" || echo "用户 $user 创建失败"
done

执行步骤

  1. 保存脚本为 create_users.sh
  2. 赋予执行权限:chmod +x create_users.sh
  3. 执行脚本:./create_users.sh

7. 常见易错点总结

  1. 变量赋值空格a = 10 错误,必须为 a=10
  2. 中括号空格[条件] 需写成 [ 条件 ](如 [ $a -gt 5 ])。
  3. 路径问题:执行脚本需用 ./脚本名,直接输入 脚本名 会提示 “命令未找到”。
  4. 转义符遗漏:使用 expr 计算乘法时,* 需转义为 \*(如 expr 5 \* 3)。
  5. 文件格式错误:Windows 格式文件需转换为 Unix 格式(使用 dos2unix)。

8. 拓展知识

8.1 脚本可移植性
  • 推荐头部#!/usr/bin/env bash,使用 env 命令自动查找 Bash 路径,避免硬编码。
  • 兼容性检查:使用 sh 命令测试脚本在旧版 Shell 中的运行情况。
8.2 权限设置最佳实践
  • 最小权限原则:仅赋予脚本所有者执行权限(chmod u+x 脚本名)。
  • 特殊权限setuidchmod u+s 脚本名)允许普通用户以脚本所有者权限执行。
8.3 脚本性能优化
  • 使用内置命令:优先使用 Bash 内置命令(如 echocd),避免调用外部程序。
  • 减少 I/O 操作:将多次 echo 合并为一次输出,或使用 printf 提升效率。

通过以上步骤,你可以全面掌握 Shell 脚本的基础操作,从创建、编辑到执行、调试,再到优化和实战应用。建议结合实际案例反复练习,加深对脚本执行原理的理解。

三、变量:脚本的 “数据细胞”

1. 变量基础:从存储到操作

1.1 变量定义与引用

定义变量

name="Alice"          # 字符串变量(值含空格需用引号包裹)
age=25                # 数值变量(本质为字符串,可参与计算)
file_path="/etc/passwd"  # 路径变量

关键规则

  • 变量名必须以字母或下划线开头,区分大小写(如 Name 和 name 是不同变量)。
  • 等号两边不能有空格(name = "Alice" 会报错)。

引用变量

echo "姓名:$name,年龄:${age}岁"
# 输出:姓名:Alice,年龄:25岁

推荐写法:使用 ${变量名} 避免歧义,例如:

fruit="apple"
echo "${fruit}s"  # 输出:apples(正确)
echo "$fruits"    # 输出:(错误,变量名歧义)
1.2 单引号 vs 双引号
符号特性示例
''原样输出,不解析变量和转义符echo '$name' → $name
""解析变量和转义符(如 \n 换行)echo "$name\n" → Alice 换行

实战场景

msg='当前用户:$USER,主目录:$HOME'
echo $msg  # 输出:当前用户:$USER,主目录:$HOMEmsg="当前用户:$USER,主目录:$HOME"
echo $msg  # 输出:当前用户:root,主目录:/root

2. 数值计算:从基础到高级

2.1 算术运算符
运算符示例(a=10b=3结果
+$((a + b))13
-$((a - b))7
*$((a * b))30
/$((a / b))3
%$((a % b))1

推荐方法

# 方法 1:$(( ))(简洁高效)
sum=$((5 + 3))          # 8
product=$((5 * 3))      # 15# 方法 2:expr(需转义乘号)
sum=$(expr 5 + 3)       # 8
product=$(expr 5 \* 3)  # 15(注意 `\*`)
2.2 数值运算实战

案例:计算圆的面积

#!/bin/bash
radius=5
area=$((3.14 * radius * radius))  # 注意:整数运算会截断小数
echo "半径为 $radius 的圆面积:$area"  # 输出:78(实际应为 78.5)

改进方案

area=$(echo "3.14 * $radius * $radius" | bc)  # 使用 bc 工具支持浮点运算
echo "半径为 $radius 的圆面积:$area"  # 输出:78.5

3. 标准变量:系统级的数据仓库

3.1 常用环境变量
变量名含义示例(管理员用户)
$HOME用户主目录/root
$PWD当前工作目录/home/user/scripts
$USER当前用户名root
$PATH命令搜索路径:/usr/bin:/bin
$HOSTNAME主机名localhost.localdomain

实战示例

echo "当前用户:$USER,主目录:$HOME"
# 输出:当前用户:root,主目录:/root
3.2 永久设置环境变量
  1. 临时生效(当前终端有效):
    export MY_VAR="自定义变量"
    
  2. 永久生效(所有终端有效):
    # 编辑用户配置文件
    nano ~/.bashrc
    # 在文件末尾添加
    export MY_VAR="自定义变量"
    # 使配置生效
    source ~/.bashrc
    

4. 特殊变量:脚本参数与状态

4.1 位置参数
变量含义示例(脚本 test.sh 1 2 "a b"
$0脚本名称test.sh
$1~$9第 1 到第 9 个参数$1=1$2=2$3=a b
${10}第 10 个参数(需用大括号)$10=10(若参数足够)

示例脚本 args.sh

#!/bin/bash
echo "脚本名:$0"
echo "第一个参数:$1"
echo "第十个参数:${10}"

运行:

./args.sh 1 2 3 4 5 6 7 8 9 10
# 输出:
# 脚本名:./args.sh
# 第一个参数:1
# 第十个参数:10
4.2 其他特殊变量
变量含义示例(脚本 test.sh
$#参数个数3(若传递 3 个参数)
$@所有参数(独立字符串)1 2 "a b"
$*所有参数(单个字符串)1 2 a b(空格丢失)
$$脚本进程号(PID)12345(实际 PID)
$?上条命令退出状态(0 = 成功)0(若命令成功)

实战案例

#!/bin/bash
echo "参数个数:$#"
echo "所有参数(\$@):$@"
echo "所有参数(\$*):$*"

运行:

./test.sh hello "world!"
# 输出:
# 参数个数:2
# 所有参数($@):hello world!
# 所有参数($*):hello world!

5. 变量作用域:从全局到局部

5.1 全局变量

定义:在脚本任何位置定义的变量,默认在整个脚本有效。

#!/bin/bash
global_var="全局变量"function show_var() {echo "函数内访问全局变量:$global_var"
}show_var  # 输出:函数内访问全局变量:全局变量
echo "函数外访问全局变量:$global_var"  # 输出:函数外访问全局变量:全局变量
5.2 局部变量

定义:使用 local 关键字在函数内定义的变量,仅在函数内有效。

#!/bin/bash
function local_var_demo() {local local_var="局部变量"  # 仅函数内有效echo "函数内访问局部变量:$local_var"
}local_var_demo  # 输出:函数内访问局部变量:局部变量
echo "函数外访问局部变量:$local_var"  # 输出:函数外访问局部变量:(空)

6. 高级变量操作:让脚本更灵活

6.1 变量替换
语法作用示例(str="hello world"
${str#h*o}从头部删除最短匹配 h*oworld
${str##h*o}从头部删除最长匹配 h*orld
${str%ld}从尾部删除最短匹配 ldhello wor
${str%%ld}从尾部删除最长匹配 ldhello wor
${str/world/Shell}替换第一个匹配项hello Shell
${str//l/LL}替换所有匹配项heLLo worLLd

实战案例

path="/home/user/documents/report.txt"
# 提取文件名
filename=${path##*/}  # 输出:report.txt
# 提取文件类型
extension=${filename##*.}  # 输出:txt
6.2 命令替换

语法

变量=$(命令)  # 推荐写法
变量=`命令`  # 反引号写法(易混淆)

示例

# 获取当前日期
date=$(date +%Y-%m-%d)
echo "今天日期:$date"  # 输出:今天日期:2023-10-01# 获取文件行数
line_count=$(wc -l < /etc/passwd)
echo "用户文件行数:$line_count"  # 输出:用户文件行数:42

7. 常见易错点与解决方案

7.1 变量赋值空格错误

错误示例

name = "Alice"  # 报错:-bash: name: 未找到命令

解决方案

name="Alice"  # 正确写法
7.2 中括号条件判断空格缺失

错误示例

if [ $age -gt 18 ]; then  # 正确
if [ $age-gt 18 ]; then  # 错误(缺少空格)
7.3 数组定义逗号分隔

错误示例

names=("Kanye", "Edison", "Fish")  # 错误(逗号分隔)

解决方案

names=("Kanye" "Edison" "Fish")  # 正确(空格分隔)
7.4 变量命名冲突

错误示例

USER="自定义用户"  # 覆盖系统变量 $USER

解决方案

user="自定义用户"  # 使用小写字母避免冲突

8. 拓展知识:让变量更强大

8.1 只读变量
readonly PI=3.14  # 定义只读变量
PI=3.1415        # 报错:PI: 只读变量
8.2 删除变量
name="Alice"
unset name       # 删除变量
echo $name       # 输出:(空)
8.3 变量类型转换
num="123"
echo $((num + 100))  # 输出:223(自动转换为整数)

9. 实战案例:变量综合应用

9.1 批量重命名文件
#!/bin/bash
# 将当前目录下所有 .txt 文件重命名为 .log
for file in *.txt; donew_name="${file%.txt}.log"  # 替换扩展名mv "$file" "$new_name"echo "重命名:$file → $new_name"
done
9.2 动态获取系统信息
#!/bin/bash
# 获取系统负载、内存使用、用户数
load=$(uptime | awk -F 'load average:' '{print $2}' | cut -d ',' -f 1)
mem_used=$(free -h | awk '/Mem:/ {print $3}')
user_count=$(who | wc -l)echo "系统负载:$load"
echo "内存使用:$mem_used"
echo "在线用户:$user_count"

10. 总结:变量的 “生存法则”

  • 命名规范:小写字母开头,避免与系统变量冲突。
  • 引号使用:值含空格或特殊字符时,优先使用双引号。
  • 作用域控制:函数内变量使用 local 声明,避免全局污染。
  • 性能优化:算术运算用 $(( )),命令替换用 $( )

通过以上内容,你将掌握 Shell 变量的核心操作,从基础定义到高级应用,再到实战案例,逐步提升脚本编写能力。变量是 Shell 编程的基石,熟练运用它们能让你的脚本更灵活、高效!

四、运算符与条件判断

1. 关系运算符(判断条件)

(1)数字比较
运算符含义示例(a=10b=20
-eq等于[ $a -eq $b ] → 假
-ne不等于[ $a -ne $b ] → 真
-gt大于[ $a -gt $b ] → 假
-lt小于[ $a -lt $b ] → 真
-ge大于等于[ $a -ge $b ] → 假
-le小于等于[ $a -le $b ] → 真
(2)字符串比较
运算符含义示例
-z字符串为空[ -z "" ] → 真
-n字符串非空[ -n "abc" ] → 真
==字符串相等[ "a" == "a" ] → 真
!=字符串不等[ "a" != "b" ] → 真
\>字符串排序大于(需转义)[ "b" \> "a" ] → 真
\<字符串排序小于(需转义)[ "a" \< "b" ] → 真
(3)文件判断
运算符含义示例
-e文件 / 目录存在[ -e /etc/passwd ] → 真
-f是普通文件[ -f first_script.sh ] → 真(若文件存在)
-d是目录[ -d /home ] → 真
-r文件可读[ -r /etc/shadow ] → 假(普通用户不可读)
-w文件可写[ -w first_script.sh ] → 真(若有写权限)
-x文件可执行[ -x first_script.sh ] → 真(若有执行权限)

2. 逻辑运算符(组合条件)

运算符含义示例
-a逻辑与(AND)[ $a -gt 5 -a $a -lt 15 ] → a 在 6-14 之间为真
-o逻辑或(OR)[ -f file -o -d dir ] → 文件或目录存在为真
!逻辑非(NOT)[ ! -e file ] → 文件不存在为真

注意

  • 条件判断需用中括号 [ ],且括号前后必须留空格(如 [ $a -gt 5 ],否则报错)。
  • 复杂条件可用 && 和 ||(适用于命令级逻辑,如 command1 && command2 表示 command1 成功后执行 command2)。

五、数组:批量数据处理

1. 定义数组

  • 方式 1:直接赋值(下标从 0 开始)
    fruits=("apple" "banana" "orange")  # 定义包含三个元素的数组
    
  • 方式 2:指定下标(支持稀疏数组)
    numbers[0]=10
    numbers[2]=30  # 下标 1 未定义,值为空
    
  • 方式 3:省略下标(自动递增)
    array=()
    array+=("one")  # 追加元素
    array+=("two")
    

2. 访问数组元素

  • 获取单个元素${数组名[下标]}
    echo ${fruits[1]}  # 输出:banana
    
  • 获取所有元素${数组名[@]} 或 ${数组名[*]}
    echo ${fruits[@]}  # 输出:apple banana orange
    
  • 获取数组长度${#数组名[@]}
    echo ${#fruits[@]}  # 输出:3
    
  • 切片操作(从下标 1 开始,取 2 个元素)
    echo ${fruits[@]:1:2}  # 输出:banana orange
    

3. 遍历数组示例

#!/bin/bash
nums=(1 3 5 7 9)
for num in ${nums[@]}; do  # 遍历数组所有元素echo "当前数字:$num"
done
# 输出:
# 当前数字:1
# 当前数字:3
# 当前数字:5
# 当前数字:7
# 当前数字:9

六、流程控制:脚本的 “逻辑大脑”

在 Shell 编程中,流程控制是实现复杂逻辑的核心。通过条件判断和循环结构,脚本可以根据不同场景执行不同操作,实现自动化任务。本节将从基础语法到实战案例,逐步解析 Shell 流程控制的核心知识点。

1. 条件判断:让脚本 “会思考”

1.1 if 语句:最基础的条件分支

语法格式

if [ 条件 ]; then命令1  # 条件为真时执行
elif [ 条件2 ]; then  # 可选,多个条件分支命令2
else  # 可选,所有条件不满足时执行命令3
fi  # 必须以 fi 结束

关键细节

  • 条件表达式:需用中括号 [ ] 包裹,且括号前后必须留空格(如 [ $a -gt 5 ],否则报错)。
  • 文件判断参数:常用 -e(存在)、-f(普通文件)、-d(目录)等(见下表)。
运算符含义示例
-e文件 / 目录存在[ -e /etc/passwd ] → 真
-f是普通文件[ -f script.sh ] → 真(若文件存在)
-d是目录[ -d /home ] → 真

示例:判断文件类型

#!/bin/bash
file="./test.txt"if [ -e "$file" ]; then          # 文件存在if [ -f "$file" ]; then         # 是普通文件echo "文件 $file 是普通文件"elif [ -d "$file" ]; then       # 是目录echo "文件 $file 是目录"else                            # 其他类型(如链接、设备文件)echo "文件 $file 是特殊文件"fi
elseecho "文件 $file 不存在"
fi
1.2 case 语句:模式匹配的高效选择

语法格式

case 变量 in模式1)命令1;;  # 必须用双分号结束分支模式2)命令2;;*)  # 通配符:匹配所有未定义的模式命令3;;
esac  # 必须以 esac 结束

适用场景

  • 菜单驱动程序(如用户输入 1-5 选择操作)。
  • 文件类型判断(如根据扩展名执行不同解压命令)。

示例:简易菜单程序

#!/bin/bash
echo "请选择操作(1-3):"
echo "1. 查看当前目录"
echo "2. 查看系统时间"
echo "3. 退出程序"
read choicecase $choice in1)ls -l  # 列出当前目录文件;;2)date +"%Y-%m-%d %H:%M:%S"  # 显示当前时间;;3)echo "退出程序"exit 0  # 退出脚本;;*)echo "无效选择!请输入 1-3";;
esac

2. 循环结构:让脚本 “重复执行”

2.1 for 循环:遍历列表或范围

格式 1:遍历列表(新手友好)

for 变量 in 元素1 元素2 元素3; do命令  # 对每个元素执行操作
done

示例:打印所有水果

fruits=("apple" "banana" "orange")
for fruit in ${fruits[@]}; doecho "当前水果:$fruit"
done
# 输出:
# 当前水果:apple
# 当前水果:banana
# 当前水果:orange

格式 2:C 语言风格(指定次数)

for ((初始值; 条件; 增量)); do命令  # 按次数循环
done

示例:计算 1+2+…+10

sum=0
for ((i=1; i<=10; i++)); dosum=$((sum + i))
done
echo "总和:$sum"  # 输出:55
2.2 while 循环:条件驱动的重复

语法格式

while [ 条件 ]; do命令  # 条件为真时持续执行
done

示例:逐行读取文件

#!/bin/bash
file="users.txt"
while read line; do  # 每次读取文件一行到变量 lineecho "用户:$line"
done < "$file"  # 从文件获取输入(重定向)
2.3 until 循环:反条件循环

语法格式

until [ 条件 ]; do命令  # 条件为假时持续执行,直到条件为真
done

示例:等待文件生成

until [ -e "data.csv" ]; do  # 直到文件存在echo "等待 data.csv 生成..."sleep 1  # 休眠 1 秒
done
echo "文件已生成!"

3. 循环控制:让流程更灵活

3.1 break 与 continue
关键字作用示例
break跳出当前循环(类似 C 语言)for i in 1 2 3; do if [ $i -eq 2 ]; then break; fi; done(仅打印 1)
continue跳过当前循环迭代for i in 1 2 3; do if [ $i -eq 2 ]; then continue; fi; echo $i; done(打印 1, 3)
3.2 嵌套循环:解决复杂逻辑

示例:打印乘法表

for i in {1..9}; dofor j in {1..9}; doecho -n "$i×$j=$((i*j)) "  # -n 不换行doneecho  # 换行
done

4. 函数:代码复用的 “积木”

4.1 定义与调用函数

语法格式

# 格式 1(简洁写法)
函数名() {local 变量  # 声明局部变量(仅限函数内使用)命令       # 函数逻辑return 退出码  # 可选,0 表示成功,非 0 表示失败
}# 格式 2(显式声明)
function 函数名() {命令
}

示例:计算两数之和

#!/bin/bash
# 定义函数:接收两个参数,返回和
add() {local a=$1  # 局部变量,避免污染全局作用域local b=$2echo $((a + b))  # 通过 echo 输出结果(推荐)return 0        # 返回成功状态
}# 调用函数并获取结果
result=$(add 5 3)
echo "5 + 3 = $result"  # 输出:8
echo "函数返回值:$?"    # 输出:0(成功)
4.2 函数参数传递
  • 位置参数:函数内通过 $1$2 等获取调用时传递的参数。
  • 参数验证:调用前检查参数个数,避免空指针错误。
    add() {if [ $# -ne 2 ]; then  # 检查参数个数是否为 2echo "错误:需要 2 个参数"return 1fi# 逻辑代码
    }
    

5. 常见易错点与解决方案

5.1 中括号空格缺失

错误示例

if [ $age>18 ]; then  # 错误(缺少空格)
if [ $age -gt 18 ]; then  # 正确

解决方案:始终在中括号内外留空格([ 条件 ])。

5.2 case 分支遗漏 ;;

错误示例

case $choice in1) echo "选项 1"  # 缺少 ;;,导致语法错误
esac

解决方案:每个分支必须以 ;; 结束。

5.3 无限循环陷阱

错误示例

while [ 1 -eq 1 ]; do  # 条件永远为真,导致无限循环echo "陷阱!"
done

解决方案:确保循环条件最终会变为假,或用 break 强制退出。

6. 实战案例:流程控制综合应用

6.1 文件备份脚本
#!/bin/bash
# 功能:判断目录是否存在,存在则备份,否则创建并备份backup_dir="/backup"
source_dir="/data"# 判断备份目录是否存在
if [ ! -d "$backup_dir" ]; thenmkdir -p "$backup_dir"  # 创建目录(-p 自动创建父目录)echo "创建备份目录:$backup_dir"
fi# 备份数据(使用时间戳命名备份文件)
timestamp=$(date +%Y%m%d%H%M%S)
tar -czf "$backup_dir/data_$timestamp.tar.gz" "$source_dir"echo "备份完成!文件路径:$backup_dir/data_$timestamp.tar.gz"
6.2 交互式猜数字游戏
#!/bin/bash
# 生成 1-100 随机数
num=$((RANDOM % 100 + 1))
attempts=0  # 记录尝试次数while true; do  # 无限循环,直到猜对read -p "请输入一个数字(1-100):" guessattempts=$((attempts + 1))if [ $guess -eq $num ]; thenecho "恭喜!你在 $attempts 次内猜对了!"break  # 跳出循环elif [ $guess -gt $num ]; thenecho "猜大了!再试一次。"elseecho "猜小了!再试一次。"fi
done

7. 拓展知识:让流程控制更强大

7.1 复合条件表达式
  • 逻辑与&&(如 command1 && command2,仅当 command1 成功时执行 command2)。
  • 逻辑或||(如 command1 || command2,仅当 command1 失败时执行 command2)。
7.2 函数递归

示例:计算阶乘(递归实现)

factorial() {local n=$1if [ $n -eq 0 ]; thenecho 1elseecho $((n * $(factorial $((n-1)))))fi
}result=$(factorial 5)
echo "5 的阶乘:$result"  # 输出:120
7.3 循环性能优化
  • 减少 I/O:将多次 echo 合并为一次,或使用 printf 提升效率。
  • 避免全局变量:函数内使用 local 声明变量,提高代码可读性和安全性。

8. 总结:流程控制的 “黄金法则”

  1. 条件判断:善用 if 和 case,复杂逻辑用 case 提高可读性。
  2. 循环选择:列表遍历用 for,条件驱动用 while,反向条件用 until
  3. 函数设计:参数验证、局部变量、明确返回值,提升代码复用性。
  4. 调试技巧:用 set -x 开启调试模式,查看循环和条件的执行流程。

通过掌握流程控制,你将能编写具备 “智能” 的 Shell 脚本,实现从简单任务到复杂自动

七、函数:代码复用的核心

在 Shell 编程中,函数是实现代码复用和模块化的关键。通过将重复或通用的逻辑封装为函数,不仅能减少代码冗余,还能提高脚本的可读性和维护性。本节将从函数的基础语法出发,结合实战案例,逐步解析函数的核心知识点。

1. 函数基础:从定义到调用

1.1 函数定义的两种格式

格式 1:简洁写法(推荐新手)

函数名() {命令1命令2return 退出码  # 可选,默认返回最后一条命令的状态(0-255)
}

格式 2:显式声明(清晰易读)

function 函数名() {命令
}

关键说明

  • function 关键字可选,但显式声明能提高代码可读性。
  • return 用于指定退出码(0 表示成功,非 0 表示失败),省略时返回最后一条命令的状态。

示例:定义一个打招呼函数

greet() {echo "Hello, $1!"  # $1 是函数的第一个参数return 10  # 手动设置返回码为 10
}
1.2 调用函数与参数传递

语法

函数名 参数1 参数2 参数3  # 参数之间用空格分隔

示例:调用打招呼函数

greet "Alice"  # 输出:Hello, Alice!
echo "函数返回码:$?"  # 输出:10(通过 $? 获取返回码)

2. 参数处理:让函数更灵活

2.1 位置参数:函数的 “输入变量”
变量含义示例(函数调用 add 5 3
$1第一个参数5
$2第二个参数3
$#参数个数2
$@所有参数(独立字符串)5 3

示例:计算两数之和的函数

add() {local sum=$(( $1 + $2 ))  # local 声明局部变量,避免污染全局作用域echo "和为:$sum"  # 输出结果(推荐通过 echo 返回数据)return 0  # 返回成功状态码
}# 调用函数并获取结果
result=$(add 5 3)  # 将函数输出赋值给变量
echo "计算结果:$result"  # 输出:计算结果:8
2.2 参数验证:避免无效输入

场景:当函数需要固定数量的参数时,先检查参数个数。

add() {if [ $# -ne 2 ]; then  # 检查参数是否为 2 个echo "错误:需要 2 个参数,实际 $# 个"return 1  # 返回错误码filocal sum=$(( $1 + $2 ))echo $sum
}# 调用错误示例
add 5  # 输出:错误:需要 2 个参数,实际 1 个
echo "返回码:$?"  # 输出:1

3. 变量作用域:避免 “变量污染”

3.1 全局变量:脚本内处处可见

特点:在函数外定义的变量,或函数内未用 local 声明的变量,均可在全局访问。

global_var="全局变量"show_global() {echo "函数内访问:$global_var"  # 可直接访问全局变量
}show_global  # 输出:函数内访问:全局变量
echo "函数外访问:$global_var"  # 输出:函数外访问:全局变量
3.2 局部变量:函数内的 “私有数据”

语法:用 local 关键字声明,仅在函数内有效。

function local_demo() {local local_var="局部变量"  # 局部变量echo "函数内:$local_var"
}local_demo  # 输出:函数内:局部变量
echo "函数外:$local_var"  # 输出:(空,外部无法访问)

4. 返回值:状态与数据的双重传递

4.1 返回码(状态值)
  • 用途:通过 return 声明,用于表示函数执行是否成功(0 = 成功,非 0 = 失败)。
  • 获取方式:调用后通过 $? 获取。
check_file() {if [ -e "$1" ]; thenreturn 0  # 文件存在,返回成功码elsereturn 1  # 文件不存在,返回错误码fi
}check_file "test.sh"
if [ $? -eq 0 ]; thenecho "文件存在"
elseecho "文件不存在"
fi
4.2 数据返回(推荐方式)
  • 用途:通过 echo 或 printf 输出数据,适用于返回字符串、数值等复杂结果。
  • 获取方式:用命令替换 $(函数名) 接收输出。
get_current_time() {date +"%Y-%m-%d %H:%M:%S"  # 直接输出时间
}time_now=$(get_current_time)
echo "当前时间:$time_now"  # 输出:当前时间:2023-10-01 15:30:00

5. 高级技巧:让函数更强大

5.1 函数递归:用循环逻辑解决复杂问题

场景:计算阶乘、斐波那契数列等递归问题。

# 计算 n 的阶乘(递归实现)
factorial() {local n=$1if [ $n -eq 0 ]; thenecho 1  # 递归终止条件elseecho $(( $n * $(factorial $((n-1))) ))  # 递归调用fi
}result=$(factorial 5)
echo "5 的阶乘:$result"  # 输出:120
5.2 默认参数:让函数更 “智能”

语法:通过 ${参数:-默认值} 实现参数默认值。

greet() {local name=${1:-"Guest"}  # 若未传参,默认值为 "Guest"echo "Hello, $name!"
}greet  # 输出:Hello, Guest!(未传参时用默认值)
greet "Alice"  # 输出:Hello, Alice!(传参时用实际值)
5.3 可变参数:处理不确定数量的输入

场景:函数需要接收任意数量的参数(如日志函数记录多个信息)。

log() {local timestamp=$(date +"%Y-%m-%d %H:%M:%S")echo "[${timestamp}] $*"  # $* 表示所有参数(视为单个字符串)
}log "用户登录" "IP: 192.168.1.1"  # 输出:[2023-10-01 15:30:00] 用户登录 IP: 192.168.1.1

6. 常见易错点与解决方案

6.1 忘记声明局部变量导致全局污染

错误示例

count=0  # 全局变量
increment() {count=$((count + 1))  # 未用 local,修改全局变量
}increment
echo "全局 count:$count"  # 输出:1(全局变量被修改)

解决方案:在函数内用 local 声明变量:

increment() {local count=$((count + 1))  # 局部变量,不影响全局
}
6.2 参数索引错误(如 $0 误用)

错误示例

add() {echo $0  # 输出脚本名,而非第一个参数($0 是脚本名,参数从 $1 开始)
}

解决方案:牢记函数内参数从 $1 开始,$0 是脚本名。

6.3 返回码与数据返回混淆

错误做法:用 return 返回数据(仅支持 0-255 的整数)。

add() {return $((5 + 3))  # 错误,return 只能返回状态码
}

正确做法:用 echo 输出数据,return 仅用于状态码。

7. 实战案例:函数综合应用

7.1 文件操作函数库

需求:封装常用文件操作函数,如创建目录、复制文件。

#!/bin/bash# 函数 1:创建目录(带错误处理)
create_dir() {local dir=$1if [ -d "$dir" ]; thenecho "目录 $dir 已存在"return 1fimkdir -p "$dir"if [ $? -eq 0 ]; thenecho "目录 $dir 创建成功"return 0elseecho "目录 $dir 创建失败"return 1fi
}# 函数 2:复制文件到目录
copy_file() {local src=$1local dest_dir=$2if [ ! -f "$src" ]; thenecho "源文件 $src 不存在"return 1fiif [ ! -d "$dest_dir" ]; thencreate_dir "$dest_dir"  # 调用其他函数if [ $? -ne 0 ]; thenreturn 1fificp "$src" "$dest_dir"echo "文件 $src 复制到 $dest_dir 成功"return 0
}# 调用函数
copy_file "data.txt" "backup"
7.2 交互式菜单函数

需求:通过函数实现菜单驱动的用户交互。

show_menu() {echo "===== 菜单 ====="echo "1. 查看系统信息"echo "2. 退出程序"echo "================"
}handle_choice() {local choice=$1case $choice in1)uname -a  # 显示系统信息;;2)echo "退出程序"exit 0;;*)echo "无效选择!";;esac
}# 主程序
while true; doshow_menu  # 调用菜单函数read -p "请选择:" choicehandle_choice "$choice"  # 调用选择处理函数
done

8. 拓展知识:函数的进阶应用

8.1 函数库管理
  • 创建函数文件:将常用函数保存到独立文件(如 utils.sh)。
    # utils.sh 内容
    function add() { ... }
    function greet() { ... }
    
  • 引入函数库:通过 source 命令在脚本中引用。
    source utils.sh  # 使 utils.sh 中的函数在当前脚本生效
    add 5 3  # 直接调用
    
8.2 函数调试技巧
  • 开启调试模式:用 set -x 跟踪函数执行步骤。
    set -x  # 开启调试
    add 5 3  # 显示每一步执行的命令
    set +x  # 关闭调试
    
  • 打印参数信息:在函数开头输出参数,确认输入是否正确。
    add() {echo "接收到的参数:$1, $2"  # 调试用输出...
    }
    

9. 总结:函数的 “复用哲学”

  • 代码复用:将重复逻辑封装为函数,避免 “重复造轮子”。
  • 模块化设计:每个函数专注于一个独立功能(如文件操作、数据计算),提高可维护性。
  • 错误处理:通过参数验证和返回码,让函数更健壮。

掌握函数后,你将从 “编写零散命令” 进阶到 “构建结构化脚本”。建议从简单函数开始,逐步积累常用工具函

八、实战案例:判断闰年

需求

输入年份,判断是否为闰年(闰年条件:能被 4 整除且不能被 100 整除,或能被 400 整除)。

脚本实现

#!/bin/bash
read -p "请输入年份:" year# 组合条件:(year%400==0) 或 (year%4==0 且 year%100!=0)
if [ $((year % 400)) -eq 0 ] || [ \( $((year % 4)) -eq 0 -a $((year % 100)) -ne 0 \) ]; thenecho "$year 是闰年"
elseecho "$year 是平年"
fi

关键点

  • \(` 和 `\) 用于转义括号,确保条件正确组合。
  • || 表示逻辑或,-a 表示逻辑与。

九、常见易错点总结

  1. 变量赋值空格a = 10 错误,必须为 a=10(等号前后不能有空格)。
  2. 中括号空格[条件] 需写成 [ 条件 ],否则报错(如 [a -gt 5] 错误,应为 [ $a -gt 5 ])。
  3. 文件路径错误:执行脚本时需用 ./脚本名,直接输入 脚本名 会提示 “命令未找到”。
  4. 转义符遗漏:使用 expr 计算乘法时,* 需转义为 \*,或改用 $(( )) 避免转义。
  5. 字符串比较误区:比较字符串是否相等时,= 前后需留空格(如 [ "$a" = "$b" ]),否则会被视为赋值。

十、总结

Shell 编程是 Linux 自动化的核心技能,从简单的脚本到复杂的流程控制,需要通过大量实践掌握。新手入门时,建议:

  1. 从单个知识点入手,如变量、循环、函数,逐个击破。
  2. 每学一个语法,编写小例子验证效果,理解背后逻辑。
  3. 遇到错误时,善用 echo 打印变量值,或用 bash -x 脚本名 调试(显示每行执行过程)。

记住:Shell 脚本的魅力在于 “用简单命令组合实现强大功能”,坚持练习,你会逐渐体会到它的高效与便捷!

相关文章:

linux入门六:Linux Shell 编程

一、Shell 概述 1. 什么是 Shell&#xff1f; Shell 是 Linux 系统中用户与内核之间的桥梁&#xff0c;作为 命令解析器&#xff0c;它负责将用户输入的文本命令转换为计算机可执行的机器指令。 本质&#xff1a;Shell 是一个程序&#xff08;如常见的 Bash、Zsh&#xff09…...

Franka 机器人x Dexterity Gen引领遥操作精细任务新时代

教授机器人工具灵活操作难题 在教授机器人灵活使用工具方面&#xff0c;目前主要有两种策略&#xff1a;一是人类遥控&#xff08;用于模仿学习&#xff09;&#xff0c;二是模拟到现实的强化学习。然而&#xff0c;这两种方法均存在明显的局限性。 1、人类遥控&#xff08;用…...

网络通讯协议UDP转发TCP工具_UdpToTcpRelay_双向版

UDP/TCP网络转发器程序说明书 1. 程序概述 本程序是一个高性能网络数据转发工具&#xff0c;支持UDP和TCP协议之间的双向数据转发&#xff0c;并具备以下核心功能&#xff1a; 协议转换&#xff1a;实现UDP↔TCP协议转换数据转换&#xff1a;支持十六进制/ASCII格式的数据转…...

深入理解 RxSwift 中的 Driver:用法与实践

目录 前言 一、什么是Driver 1.不会发出错误 2.主线程保证 3.可重放 4.易于绑定 二、Driver vs Observable 三、使用场景 1.绑定数据到UI控件 2.响应用户交互 3.需要线程安全的逻辑 4.如何使用Driver&#xff1f; 1.绑定文本输入到Label 2.处理按钮点击事件 3…...

【XML基础-3】深入理解XML Schema:XML的强大语义约束机制

XML&#xff08;可扩展标记语言&#xff09;作为数据交换的标准格式&#xff0c;在当今信息技术领域扮演着重要角色。然而&#xff0c;仅有基本的XML语法规则往往不足以满足复杂的数据验证需求。这正是XML Schema发挥作用的地方——它为XML文档提供了强大的语义约束能力。本文将…...

神经网络语言模型与统计语言模型的比较

神经网络语言模型&#xff08;Neural Language Models, NLMs&#xff09;与统计语言模型&#xff08;Statistical Language Models, SLMs&#xff09;是自然语言处理&#xff08;NLP&#xff09;中两类核心的语言建模方法&#xff0c;其核心差异体现在建模方式、表示能力、数据…...

大模型论文:CRAMMING TRAINING A LANGUAGE MODEL ON ASINGLE GPU IN ONE DAY(效率提升)-final

大模型论文&#xff1a;CRAMMING: TRAINING A LANGUAGE MODEL ON ASINGLE GPU IN ONE DAY(效率提升) 文章地址&#xff1a;https://arxiv.org/abs/2212.14034 摘要 近年来&#xff0c;语言建模的研究趋势集中在通过大规模扩展来提升性能&#xff0c;导致训练语言模型的成本变…...

构建AI应用(持续更新)

常用的框架&#xff1a; dify、coze&#xff1a;低代码模块化编程 langchain&#xff1a;面向程序人员 常规的应用&#xff1a; 语音转文字ASR&#xff0c;文字转语音TTS&#xff0c;下一步问题建议&#xff0c; 旅游计划&#xff0c;买点提取&#xff0c;情感陪聊&#x…...

【JAVA】JVM 堆内存“缓冲空间”的压缩机制及调整方法

1. 缓冲空间是否可压缩&#xff1f; 是的&#xff0c;JVM 会在满足条件时自动收缩堆内存&#xff0c;将未使用的缓冲空间释放回操作系统。但需满足以下条件&#xff1a; GC 触发堆收缩&#xff1a;某些垃圾回收器&#xff08;如 G1、Serial、Parallel&#xff09;在 Full GC …...

NLP高频面试题(三十八)——什么是LLM的灾难性遗忘?如何避免灾难性遗忘?

近年来,大语言模型在人工智能领域取得了显著进展。然而,随着模型的不断更新和新任务的引入,出现了一个重要的问题,即灾难性遗忘(Catastrophic Forgetting)。灾难性遗忘指的是大模型在连续学习新知识或新任务时,先前掌握的旧知识会迅速被覆盖或遗忘,从而导致模型在旧任务…...

Keepalived+LVS高可用集群实战:从原理到落地

在分布式系统架构中&#xff0c;服务的高可用性和负载均衡是保障业务连续性的核心要素。本文通过一次实验&#xff0c;深入探索了基于KeepalivedLVS的高可用负载均衡集群方案&#xff0c;带您从零开始理解原理、动手实践配置&#xff0c;并验证其可靠性。 一、实验目标 本次实…...

【JVM】JVM调优实战

&#x1f600;大家好&#xff0c;我是白晨&#xff0c;一个不是很能熬夜&#x1f62b;&#xff0c;但是也想日更的人✈。如果喜欢这篇文章&#xff0c;点个赞&#x1f44d;&#xff0c;关注一下&#x1f440;白晨吧&#xff01;你的支持就是我最大的动力&#xff01;&#x1f4…...

Linux系统安全-开发中注意哪些操作系统安全

Hey小伙伴们~&#x1f44b; 在Linux开发中&#xff0c;确保操作系统的安全真的太太太重要啦&#xff01;&#x1f6e1;️ 今天就来和大家聊聊几个超关键的注意事项&#xff0c;记得拿小本本记下来哦&#xff01;&#x1f4dd; 1️⃣ ‌用户管理与权限控制‌&#x1f465; 合理…...

Qt问题之 告别软件因系统默认中文输入法导致错误退出的烦恼

1. 问题 使用Qt进行研发时&#xff0c;遇到一个问题&#xff0c;当在系统默认输入法中文&#xff08;英文输入法或者搜狗就不会触发闪退&#xff09;的情况下&#xff0c;选中QTableWidget控件&#xff08;QTableWidgetItem有焦点&#xff0c;但是不双击&#xff09;&#xff…...

2025 年“认证杯”数学中国数学建模网络挑战赛 D题 无人机送货规划

在快递和外卖等短途递送小件货物的业务中&#xff0c;无人机或许大有可为。现 有一个城市的快递仓库准备使用若干无人机进行派件&#xff0c;设有若干架无人机从 仓库出发&#xff0c;分别装载了若干快递包裹。每架无人机装载的包裹的收货地点会 被排列为一个目的地列表&#x…...

【2025年认证杯数学中国数学建模网络挑战赛】A题解题思路与模型代码

【2025年认证杯数学建模挑战赛】A题 该题为典型的空间几何建模轨道动力学建模预测问题。 ⚙ 问题一&#xff1a;利用多个天文台的同步观测&#xff0c;确定小行星与地球的相对距离 问题分析 已知若干地面天文台的观测数据&#xff1a;方位角 (Azimuth) 和 高度角 (Altitude)&…...

Redhat红帽 RHCE8.0认证体系课程

课程大小&#xff1a;7.7G 课程下载&#xff1a;https://download.csdn.net/download/m0_66047725/90546064 更多资源下载&#xff1a;关注我 红帽企业 Linux 系统的管理技能已经成为现代数据中心的核心竞争力。 Linux 在支持混合云、跨物理服务器、虚机、私有云和公共云计…...

Python 实现的运筹优化系统数学建模详解(最大最小化模型)

一、引言 在数学建模的实际应用里&#xff0c;最大最小化模型是一种极为关键的优化模型。它的核心目标是找出一组决策变量&#xff0c;让多个目标函数值里的最大值尽可能小。该模型在诸多领域&#xff0c;如资源分配、选址规划等&#xff0c;都有广泛的应用。本文将深入剖析最大…...

MySQL快速入门

MySQL快速入门 SQL语句 SQL语句概述 1.SQL 是用于访问和处理数据库的标准的计算机语言。 2.SQL指结构化查询语言&#xff0c;全称是 Structured Query Language。 3.SQL 可以访问和处理数据库。 4.SQL 是一种 ANSI&#xff08;American National Standards Institute 美国…...

离线安装 nvidia-docker2(nvidia-container-toolkit)

很多时候大家都有用docker使用gpu的需求&#xff0c;但是因为网络等原因不是那么好用&#xff0c;这里留了一个给ubuntu的安装包&#xff0c;网络好的话也提供了在线安装方式 安装 nvidia-docker2 1 离线安装 &#xff08;推荐&#xff09; unzip解压后进入目录 dpkg -i *.d…...

【自然语言处理】深度学习中文本分类实现

文本分类是NLP中最基础也是应用最广泛的任务之一&#xff0c;从无用的邮件过滤到情感分析&#xff0c;从新闻分类到智能客服&#xff0c;都离不开高效准确的文本分类技术。本文将带您全面了解文本分类的技术演进&#xff0c;从传统机器学习到深度学习&#xff0c;手把手实现一套…...

云原生运维在 2025 年的发展蓝图

随着云计算技术的不断发展和普及&#xff0c;云原生已经成为了现代应用开发和运维的主流趋势。云原生运维是指在云原生环境下&#xff0c;对应用进行部署、监控、管理和优化的过程。在 2025 年&#xff0c;云原生运维将迎来更加广阔的发展前景&#xff0c;同时也将面临着一系列…...

Windows系统Python多版本运行解决TensorFlow安装问题(附详细图文)

Windows系统Python多版本运行解决TensorFlow安装问题&#xff08;附详细图文&#xff09; 摘要 TensorFlow 无法安装&#xff1f;Python版本太高是元凶&#xff01; 本文针对Windows系统中因Python版本过高导致TensorFlow安装失败的问题&#xff0c;提供三种降级解决方案&…...

银行业务知识序言

银行业务知识体系全景解析 第一章 金融创新浪潮下的银行业务知识革命 1.1 数字化转型驱动金融业态重构 在区块链、人工智能、物联网等技术的叠加作用下&#xff0c;全球银行业正经历着"服务无形化、流程智能化、风控穿透化"的深刻变革。根据麦肯锡《2023全球银行业…...

《深度剖析分布式软总线:软时钟与时间同步机制探秘》

在分布式系统不断发展的进程中&#xff0c;设备间的协同合作变得愈发紧密和复杂。为了确保各个设备在协同工作时能够有条不紊地进行&#xff0c;就像一场精准的交响乐演出&#xff0c;每个乐器都要在正确的时间奏响音符&#xff0c;分布式软总线中的软时钟与时间同步机制应运而…...

RK3588 android12 适配 ilitek i2c接口TP

一&#xff0c;Ilitek 触摸屏简介 Ilitek 提供多种型号的触控屏控制器&#xff0c;如 ILI6480、ILI9341 等&#xff0c;采用 I2C 接口。 这些控制器能够支持多点触控&#xff0c;并具有优秀的灵敏度和响应速度。 Ilitek 的触摸屏控制器监测屏幕上的触摸事件。 当触摸发生时&a…...

pgsql:关联查询union(并集)、except(差集)、intersect(交集)

pgsql:关联查询union(并集)、except(差集)、intersect(交集)_pgsql except-CSDN博客...

模型材质共享导致的问题

问题&#xff1a;当我选中其中某个网格模型并设置color的时候&#xff0c;相同种类的颜色都被改变&#xff0c;但是打印我选中的网格模型数据其实只有一个。 导致问题的原因&#xff1a; 加载Blender模型修改材质颜色 Blender创建一个模型对象&#xff0c;设置颜色&#xff0…...

ThinkpPHP生成二维码

导入依赖 composer require endroid/qr-code 封装成函数&#xff0c;传入二维码包含的值&#xff0c;存储路径&#xff0c;二维码大小&#xff0c;二维码边距 private function getCode($content, $directory, $size 300, $margin 10){// 创建二维码对象// $content: 二…...

FLINK框架:流式处理框架Flink简介

在大数据时代&#xff0c;数据的价值不言而喻&#xff0c;谁能利用好数据&#xff0c;谁就掌握了整个行业的先机。面对海量的数据&#xff0c;如何处理数据成为了一个难题。除了海量数据外&#xff0c;实时性也是一个重要的课题&#xff0c;所以流式数据处理便登上了技术舞台&a…...

使用Python从零开始构建生成型TransformerLM并训练

在人工智能的浩瀚宇宙中&#xff0c;有一种神奇的生物&#xff0c;它拥有着强大的语言魔法&#xff0c;能够生成各种各样的文本&#xff0c;仿佛拥有无尽的创造力。它就是——Transformer 模型&#xff01;Transformer 模型的出现&#xff0c;为人工智能领域带来了一场“语言魔…...

xtrabackup备份

安装&#xff1a; https://downloads.percona.com/downloads/Percona-XtraBackup-8.0/Percona-XtraBackup-8.0.35-30/binary/tarball/percona-xtrabackup-8.0.35-30-Linux-x86_64.glibc2.17.tar.gz?_gl1*1ud2oby*_gcl_au*MTMyODM4NTk1NS4xNzM3MjUwNjQ2https://downloads.perc…...

2.3 Spark运行架构与流程

Spark运行架构与流程包括几个核心概念&#xff1a;Driver负责提交应用并初始化作业&#xff0c;Executor在工作节点上执行任务&#xff0c;作业是一系列计算任务&#xff0c;任务是作业的基本执行单元&#xff0c;阶段是一组并行任务。Spark支持多种运行模式&#xff0c;包括单…...

【Pandas】pandas DataFrame head

Pandas2.2 DataFrame Indexing, iteration 方法描述DataFrame.head([n])用于返回 DataFrame 的前几行 pandas.DataFrame.head pandas.DataFrame.head 是一个方法&#xff0c;用于返回 DataFrame 的前几行。这个方法非常有用&#xff0c;特别是在需要快速查看 DataFrame 的前…...

从递归入手一维动态规划

从递归入手一维动态规划 1. 509. 斐波那契数 1.1 思路 递归 F(i) F(i-1) F(i-2) 每个点都往下展开两个分支&#xff0c;时间复杂度为 O(2n) 。 在上图中我们可以看到 F(6) F(5) F(4)。 计算 F(6) 的时候已经展开计算过 F(5)了。而在计算 F(7)的时候&#xff0c;还需要…...

鸿蒙HarmonyOS埋点SDK,ClkLog适配鸿蒙埋点分析

ClkLog埋点分析系统&#xff0c;是一种全新的、开源的洞察方案&#xff0c;它能够帮助您捕捉每一个关键数据点&#xff0c;确保您的决策基于最准确的用户行为分析。技术人员可快速搭建私有的分析系统。 ClkLog鸿蒙埋点SDK通过手动埋点的方式实现HarmonyOS 原生应用的前端数据采…...

HarmonyOS:HMPermission权限请求框架

前段时间利用空余时间写了一个权限请求库&#xff1a;HMPermission。 一&#xff0c;简介 HMPermission 是鸿蒙系统上的一款权限请求框架&#xff0c;封装了权限请求逻辑&#xff0c;采用链式调用的方式请求权限&#xff0c;简化了权限请求的代码。 二&#xff0c;使用方法 …...

【书籍】DeepSeek谈《持续交付2.0》

目录 一、深入理解1. 核心理念升级&#xff1a;从"自动化"到"双环模型"2. 数字化转型的五大核心能力3. 关键实践与案例4. 组织与文化变革5. 与其它框架的关系6. 实际应用建议 二、对于开发实习生的帮助1. 立刻提升你的代码交付质量&#xff08;技术验证环实…...

Spring AOP 扫盲

&#x1f9d1; 博主简介&#xff1a;CSDN博客专家&#xff0c;历代文学网&#xff08;PC端可以访问&#xff1a;https://literature.sinhy.com/#/literature?__c1000&#xff0c;移动端可微信小程序搜索“历代文学”&#xff09;总架构师&#xff0c;15年工作经验&#xff0c;…...

银河麒麟v10(arm架构)部署Embedding模型bge-m3【简单版本】

硬件 服务器配置&#xff1a;鲲鹏2 * 920&#xff08;32c&#xff09; 4 * Atlas300I duo卡 参考文章 https://www.hiascend.com/developer/ascendhub/detail/07a016975cc341f3a5ae131f2b52399d 鲲鹏昇腾Atlas300Iduo部署Embedding模型和Rerank模型并连接Dify&#xff08;自…...

如何通过流程管理优化企业运营?

流程管理的本质是“用确定性的规则应对不确定性的业务”。 那么&#xff0c;具体该如何通过流程管理来优化企业的运作呢&#xff1f;以下是一些关键步骤和思路&#xff0c;或许能给到一些启发。 1. 从流程梳理开始&#xff1a;摸清现状&#xff0c;找准问题 想要管理好企业的…...

ZYNQ笔记(四):AXI GPIO

版本&#xff1a;Vivado2020.2&#xff08;Vitis&#xff09; 任务&#xff1a;使用 AXI GPIO IP 核实现按键 KEY 控制 LED 亮灭&#xff08;两个都在PL端&#xff09; 一、介绍 AXI GPIO (Advanced eXtensible Interface General Purpose Input/Output) 是 Xilinx 提供的一个可…...

Java学习手册:JVM、JRE和JDK的关系

在Java生态系统中&#xff0c;JVM&#xff08;Java虚拟机&#xff09;、JRE&#xff08;Java运行时环境&#xff09;和JDK&#xff08;Java开发工具包&#xff09;是三个核心概念。它们共同构成了Java语言运行和开发的基础。理解它们之间的关系对于Java开发者来说至关重要。本文…...

Java 并发-newFixedThreadPool

前言 为什么选择使用多线程&#xff1f;一种场景是在数据和业务处理能力出现瓶颈时&#xff0c;而服务器性能又有空闲&#xff0c;通常是cpu空闲&#xff0c;这时使用多线程就能很好的解决问题&#xff0c;而又无需加硬件&#xff0c;实际使用中&#xff0c;线程池又是最为常用…...

C# task任务异步编程提高UI的响应性

方式1&#xff1a;async/await模式 private async void button1_Click(object sender, EventArgs e){try{var result await Task.Run(() > CalculateResult());label1.Text result.ToString();}catch (Exception ex){label1.Text $"Error: {ex.Message}";}}pri…...

Spring Bean生命周期执行流程详解

文章目录 一、什么是Spring Bean生命周期&#xff1f;工作流程图&#xff1a;二、Bean生命周期执行流程验证1.编写测试代码验证结果2.源码追溯Bean初始化回调过程 一、什么是Spring Bean生命周期&#xff1f; Spring Bean生命周期是指从Bean的创建到销毁的整个过程&#xff0c…...

windows 安装 pygame( pycharm)

一、安装流程 1.查看python版本 2.检查是否安装pip 3.下载pygame安装文件 下载地址&#xff1a;https://pypi.org/project/pygame/#files 选择合适的版本&#xff08;我选择的是 python3.7 windows 64bit&#xff09;&#xff1a; 4.使用pip安装pygame 将下载好的whl文件移动到…...

Envoy网关实例异常重启排查总结

一、事件背景 于10月24日凌晨业务租户有业务应用发版上线&#xff0c;中午收到pod连续5分钟重启严重告警&#xff0c;登录管理节点查看异常重启的应用网关pod日志&#xff0c;存在内核段错误报错信息导致进程终止并触发监控检查异常并重启; 该报错主要是访问的内存超出了系统…...

WinForm真入门(13)——ListBox控件详解

WinForm ListBox 详解与案例 一、核心概念 ‌ListBox‌ 是 Windows 窗体中用于展示可滚动列表项的控件&#xff0c;支持单选或多选操作&#xff0c;适用于需要用户从固定数据集中选择一项或多项的场景‌。 二、核心属性 属性说明‌Items‌管理列表项的集合&#xff0c;支持动…...

【Linux网络编程】UDP Echo Server的实现

本文专栏&#xff1a;Linux网络编程 目录 一&#xff0c;Socket编程基础 1&#xff0c;IP地址和端口号 端口号划分范围 理解端口号和进程ID 源端口号和目的端口号 理解Socket 2&#xff0c;传输层的典型代表 3&#xff0c;网络字节序 4&#xff0c;Socket编程接口 s…...