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

linux辅助知识(Shell 脚本编程)

目录

一、什么是 Shell 脚本?

二、基础入门:脚本创建与执行

1. 脚本文件格式

2. 执行脚本的 3 种方式

三、核心语法:变量与输入输出

1. 变量定义与使用

2. 字符串处理

3. 特殊变量(脚本参数与状态)

4. 输入输出重定向

四、控制结构:条件与循环

1. 条件判断(if-else)

2. 循环(for/while)

(1)for 循环

(2)while 循环(条件为真时持续执行)

3. case 语句(多分支判断)

五、函数:代码复用

1. 函数定义与调用

2. 函数返回值

六、常用工具:文本处理与系统操作

1. 文本处理

2. 系统操作

七、错误处理与调试

1. 错误处理

2.脚本调试

八、实战示例:自动备份脚本

九、最佳实践

十、应用场景


Shell 脚本编程是 Linux/Unix 系统中自动化任务、批量处理和系统管理的核心技术。它通过将一系列命令按逻辑组织成文本文件,实现自动化执行,极大提升了工作效率。以下从基础到进阶详细介绍 Shell 脚本编程:

一、什么是 Shell 脚本?

  • Shell:是用户与操作系统内核交互的命令行解释器(如 bash、zsh、sh 等),负责解析并执行用户输入的命令。
  • Shell 脚本:将一系列 Shell 命令按逻辑顺序写入文本文件,通过解释器批量执行,实现自动化任务(如日志分析、备份、部署等)。

最常用的 Shell 是 bash(Bourne Again SHell),本文以 bash 为例讲解。

二、基础入门:脚本创建与执行

1. 脚本文件格式

Shell 脚本文件以 .sh 为扩展名(非强制),开头必须指定解释器(shebang 行):

#!/bin/bash
# 这是注释(# 开头的行为注释)
echo "Hello, Shell Script!"  # 输出内容
  • #!/bin/bash:指定脚本由 bash 解释器执行(必须放在第一行)。
2. 执行脚本的 3 种方式
  • 方式 1(推荐):赋予执行权限后直接运行

chmod +x script.sh  # 赋予执行权限
./script.sh         # 运行脚本(需在脚本所在目录)
  • 方式 2:通过 bash 解释器直接调用

    bash script.sh  # 无需执行权限,直接用 bash 运行

  • 方式 3:通过 source 或 . 执行(会在当前 Shell 环境中运行,变量可保留)

    source script.sh  # 等价于 . script.sh

三、核心语法:变量与输入输出

1. 变量定义与使用

定义变量:变量名 = 值(等号两边无空格

name="Alice"  # 字符串变量
age=25        # 数值变量

使用变量:通过 $变量名 或 ${变量名} 引用({} 用于区分边界)

echo "Name: $name"       # 输出:Name: Alice
echo "Age: ${age}岁"     # 输出:Age: 25岁({} 避免歧义)

只读变量:用 readonly 定义,无法修改

readonly pi=3.14
pi=3.1415  # 报错:pi: readonly variable

删除变量:用 unset(只读变量不可删除)

unset name  # 删除 name 变量
2. 字符串处理

单引号 vs 双引号

    单引号 '':字符串原样输出,不解析变量和转义字符

echo 'Name: $name'  # 输出:Name: $name

    双引号 "":解析变量和转义字符(如 \n 换行)

echo "Name: $name"  # 输出:Name: Alice

字符串长度${#变量名}

echo "Length of name: ${#name}"  # 输出:5("Alice" 长度为 5)

字符串截取${变量名:起始位置:长度}

str="hello world"
echo ${str:6:5}  # 输出:world(从索引 6 开始,取 5 个字符)
3. 特殊变量(脚本参数与状态)
变量含义
$0脚本文件名
$1~$n脚本的第 1~n 个参数($1 是第一个参数)
$#参数的总个数
$*所有参数的集合(作为单个字符串)
$@所有参数的集合(作为独立字符串)
$?上一个命令的退出状态(0 表示成功)
$$当前脚本的进程 ID(PID)

示例:script.sh 内容

#!/bin/bash
echo "脚本名:$0"
echo "第一个参数:$1"
echo "参数总数:$#"
echo "所有参数:$@"

执行:./script.sh apple banana,输出:

脚本名:./script.sh
第一个参数:apple
参数总数:2
所有参数:apple banana
4. 输入输出重定向

输出重定向:将命令结果写入文件(覆盖 / 追加)

echo "Hello" > output.txt  # 覆盖写入 output.txt
echo "World" >> output.txt # 追加写入 output.txt

输入重定向:从文件读取输入(替代键盘输入)

wc -l < input.txt  # 统计 input.txt 的行数(等价于 wc -l input.txt)

管道 |:将前一个命令的输出作为后一个命令的输入

ps aux | grep "python"  # 查找包含 "python" 的进程

四、控制结构:条件与循环

1. 条件判断(if-else)

语法:

if 条件; then# 条件成立时执行
elif 条件; then# 其他条件成立时执行
else# 所有条件不成立时执行
fi

条件表达式:用 [ ](test 命令的简写)或 [[ ]](bash 扩展,支持更多特性),注意括号前后必须有空格

常见判断类型:

数值比较-eq(等于)、-ne(不等于)、-gt(大于)、-lt(小于)等

a=10
b=20
if [ $a -lt $b ]; thenecho "$a < $b"
fi

字符串比较=(等于)、!=(不等于)、-z(空字符串)、-n(非空字符串)

str="test"
if [ -n "$str" ]; then  # 字符串非空echo "str is not empty"
fi

文件测试-f(普通文件)、-d(目录)、-r(可读)、-w(可写)、-x(可执行)

file="script.sh"
if [ -f "$file" ] && [ -x "$file" ]; then  # 是文件且可执行echo "$file is an executable file"
fi
2. 循环(for/while)
(1)for 循环

语法 1:遍历列表

for fruit in apple banana orange; doecho "Fruit: $fruit"
done

语法 2:类 C 风格(循环范围)

for ((i=1; i<=5; i++)); doecho "Count: $i"
done

语法 3:遍历目录文件

for file in ./test/*; do  # 遍历 test 目录下的所有文件if [ -f "$file" ]; thenecho "File: $file"fi
done
(2)while 循环(条件为真时持续执行)
count=1
while [ $count -le 3 ]; doecho "Count: $count"count=$((count + 1))  # 变量自增(算术运算用 $(( )))
done

无限循环(配合 break 退出):

while true; doread -p "输入 q 退出:" inputif [ "$input" = "q" ]; thenbreak  # 退出循环fi
done
3. case 语句(多分支判断)

适用于变量匹配多个固定值的场景:

read -p "输入分数(A/B/C):" grade
case $grade inA) echo "优秀" ;;B) echo "良好" ;;C) echo "及格" ;;*) echo "无效输入" ;;  # * 匹配所有未列出的值
esac

五、函数:代码复用

1. 函数定义与调用
# 定义函数
greet() {echo "Hello, $1!"  # $1 是函数的第一个参数
}# 调用函数(传递参数)
greet "Bob"  # 输出:Hello, Bob!
2. 函数返回值

通过 return 返回状态码(0~255,0 表示成功)

add() {return $(( $1 + $2 ))  # 返回两数之和(状态码范围限制,不适合大数值)
}
add 3 5
echo "结果:$?"  # 输出:8($? 获取上一个命令的返回值)

通过 echo 输出结果(适合返回字符串或大数值)

multiply() {echo $(( $1 * $2 ))  # 输出乘积
}
result=$(multiply 4 5)  # 用 $() 捕获输出
echo "结果:$result"  # 输出:20

六、常用工具:文本处理与系统操作

Shell 脚本的强大之处在于结合各类命令工具,常见场景:

1. 文本处理

grep:查找匹配的行(支持正则表达式)

grep "error" app.log  # 从 app.log 中查找包含 "error" 的行

awk:按列处理文本(数据提取、统计)

awk '{print $1, $3}' data.txt  # 打印 data.txt 的第 1 列和第 3 列

sed:文本替换(批量修改内容)

sed -i 's/old/new/g' file.txt  # 将 file.txt 中所有 "old" 替换为 "new"
2. 系统操作

find:查找文件

find /home -name "*.txt"  # 在 /home 下查找所有 .txt 文件

tar:压缩 / 解压文件

tar -czf backup.tar.gz ./data  # 压缩 data 目录为 backup.tar.gz

df/du:查看磁盘空间

df -h  # 查看磁盘使用情况(人类可读格式)

七、错误处理与调试

1. 错误处理
  • set -e:脚本中任何命令失败(返回非 0 状态)时立即退出

#!/bin/bash
set -e  # 开启错误退出
command1  # 若失败,脚本直接退出
command2  # 不会执行

trap:捕获信号(如脚本退出时执行清理操作)

cleanup() {echo "脚本退出,执行清理..."# 清理临时文件等操作
}
trap cleanup EXIT  # 脚本退出时调用 cleanup 函数
2.脚本调试
  • 执行时加 -x 参数:打印执行的每一条命令(方便定位问题)
bash -x script.sh  # 调试模式运行脚本

八、实战示例:自动备份脚本

#!/bin/bash
# 功能:每天备份指定目录到 /backup,并保留最近 7 天的备份# 配置参数
SOURCE_DIR="/home/user/documents"  # 要备份的目录
BACKUP_DIR="/backup"               # 备份存储目录
DATE=$(date +%Y%m%d)               # 当前日期(如 20231001)
BACKUP_FILE="$BACKUP_DIR/doc_backup_$DATE.tar.gz"# 检查源目录是否存在
if [ ! -d "$SOURCE_DIR" ]; thenecho "错误:源目录 $SOURCE_DIR 不存在!"exit 1  # 非 0 状态表示失败
fi# 创建备份目录(若不存在)
mkdir -p "$BACKUP_DIR"# 执行备份
echo "开始备份 $SOURCE_DIR 到 $BACKUP_FILE..."
tar -czf "$BACKUP_FILE" "$SOURCE_DIR"# 检查备份是否成功
if [ $? -eq 0 ]; thenecho "备份成功!"
elseecho "备份失败!"exit 1
fi# 删除 7 天前的备份
echo "清理 7 天前的备份..."
find "$BACKUP_DIR" -name "doc_backup_*.tar.gz" -mtime +7 -deleteecho "操作完成!"

九、最佳实践

  1. 注释清晰:关键步骤添加注释,说明用途和逻辑。
  2. 变量复用:将路径、配置等定义为变量,方便维护。
  3. 检查边界:执行命令前检查文件 / 目录是否存在、权限是否足够。
  4. 避免硬编码:通过参数或配置文件传递可变值。
  5. 测试脚本:先用 bash -n script.sh 检查语法错误,再逐步调试。

十、应用场景

  • 系统监控:定时检查磁盘、内存、进程状态。
  • 日志分析:批量处理日志文件,提取关键信息。
  • 自动化部署:一键部署代码、配置环境。
  • 批量处理:批量重命名文件、转换格式等。

http://www.xdnf.cn/news/1170991.html

相关文章:

  • 基于卷积神经网络与小波变换的医学图像超分辨率算法复现
  • AWE2026启动:加码AI科技,双展区联动开启产业新格局
  • 【kubernetes】-2 K8S的资源管理
  • Spring、Spring MVC、Spring Boot、Spring Cloud的联系和区别
  • 闲庭信步使用图像验证平台加速FPGA的开发:第三十课——车牌识别的FPGA实现(2)实现车牌定位
  • 类加载过程及双亲委派模型
  • 数据结构自学Day12-- 排序算法2
  • Pycharm下载、安装及配置
  • 【运维】SGLang服务器参数配置详解
  • 大数据之Hive:Hive中week相关的几个函数
  • 微调大语言模型(LLM)有多难?
  • SpringBoot全局异常报错处理和信息返回
  • Vue 脚手架基础特性
  • Maven 环境配置全攻略:从入门到实战
  • Typecho三种版权保护方法对比与实战指南
  • 渗透部分总结
  • 如何把jar包打成docker镜像(SpringBoot项目打包成Docker )部署到Linux
  • 本地代理和服务器代理区别
  • 【MyBatisPlus】一文讲清 MyBatisPlus 基本原理及基本使用方式
  • NumPy库使用教学,简单详细。
  • allegro 16.6配置CIS库报错 ORCIS-6129 ORCIS-6469
  • Matplotlib绘制各种图参考
  • 时序数据库IoTDB好不好?
  • 在 Linux 系统中基于 Nginx 搭建 openlab 网站及子页面
  • 浅谈——C++和C#差异
  • 从 COLMAP 到 3D Gaussian Splatting
  • 【面试】Redis分布式ID与锁的底层博弈:高并发下的陷阱与破局之道
  • 机器人氩弧焊保护气降成本的方法
  • kafka主题管理详解 - kafka-topics.sh
  • 苹果app应用ipa文件程序开发后如何运行到苹果iOS真机上测试?