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

Shell 脚本基础:从语法到实战全解析

Shell 脚本基础:从语法到实战全解析

在这里插入图片描述

Shell 脚本是 Linux 运维中实现自动化任务的核心工具,能够将复杂的命令序列、逻辑判断与变量管理整合为可重复执行的文本文件。本文从基础概念、语法规则到实战案例,系统讲解 Shell 脚本的编写与应用。

一、Shell 脚本基础

1. Shell 编程介绍与特性

Shell 既是命令解释器(接收用户输入的命令并执行),也是编程语言(支持变量、逻辑控制、函数等特性)。其核心作用是自动化完成 Linux 系统中的重复性、复杂性任务(如系统初始化、日志分析、服务部署等)。

Shell 语言的核心特点
特点说明
解释性语言无需编译,直接由 Shell 进程逐行解释执行,开发效率高(即编即用),但运行速度略慢。
基于字符串处理不支持复杂数据结构(如数组、对象),仅专注于字符串操作,输出也以字符形式呈现。
命令级语言脚本由 Linux 命令(如 lsgrepecho)和语法结构组成,命令组合灵活,功能强大。
版本兼容性不同 Shell 版本(如 Bash、Sh、Zsh)语法略有差异,Linux 中默认使用 Bash/bin/bash)。

2. 变量:Shell 中的数据存储

变量是 Shell 中存储数据的“容器”,本质是一块内存空间的别名,用于在脚本中重复使用数据。

(1)变量命名规则
  • 字母、数字、下划线组成,且必须以字母或下划线开头(不能以数字开头);
  • 区分大小写(nameName 是两个不同变量);
  • 建议使用“有意义的英文单词”(如 ageusername),避免无意义字符(如 a1x),提高可读性。
(2)变量类型

Shell 变量无需显式声明类型,根据赋值内容自动识别,常见类型如下:

类型定义方式与示例注意事项
字符串单引号(' ')、双引号(" ")或无引号(无空格时)。
示例:
msg='hello'
msg="hello $name"
msg=hello
1. 字符串含空格时必须加引号(如 msg="hello world");
2. 单引号(强引用):内部特殊字符(如 $#)无意义;
3. 双引号(弱引用):内部特殊字符(如 $)保留意义。
整数直接赋值数字,无需加引号。
示例:
age=20
count=100
Shell 原生不支持浮点型,需通过 bc 等工具处理小数。
布尔型true(1)或 false(0)表示逻辑真假。
示例:
is_ok=true
is_error=false
本质是字符串,需通过逻辑运算判断(如 if $is_ok; then ...)。
(3)变量引用与示例

引用变量时需在变量名前加 $,推荐用 ${变量名} 格式(避免与其他字符混淆):

# 定义变量
[root@ansible ~]# vim name.sh
name="zhang3"
age=21# 引用变量
echo "姓名:$name"          # 输出:姓名:zhang3
echo "年龄:${age}岁"       # 输出:年龄:21岁(${} 避免与“岁”混淆)
echo '姓名:${name}'        # 输出:姓名:${name}(单引号内变量无意义)执行脚本文件:
[root@ansible ~]# bash name.sh 
姓名:zhang3
年龄: 21岁
姓名:${name} 

3. 脚本执行方式

Shell 脚本(通常以 .sh 为后缀)的执行需满足“语法正确”,执行方式分 5 种,核心差异在于是否需要执行权限

执行方式语法格式是否需要执行权限说明
绝对路径执行/root/scripts/a.sh是(chmod +x a.sh需指定脚本的完整路径(从 / 开始)。
相对路径执行./a.sh需在脚本所在目录执行,./ 表示“当前目录”。
sh/bash 命令执行sh a.shbash a.sh直接调用 Shell 解释器执行脚本,无需赋予执行权限(推荐调试时使用)。
. 命令执行. a.sh(注意 . 后有空格)等同于 source,在当前 Shell 进程中执行(变量会影响当前环境)。
source 命令执行source a.sh常用于加载配置文件(如 /etc/profile),使配置立即生效。
示例:执行脚本 test.sh
# 1. 创建脚本
[root@ansible ~]# cat > test.sh << EOF
> #!/bin/bash
> echo "hello world"
> EOF# 2. 方式1:sh 命令执行(无需权限)
[root@ansible ~]# sh test.sh 
hello world# 3. 方式2:赋予权限后用相对路径执行
[root@ansible ~]# chmod +x test.sh 
[root@ansible ~]# ./test.sh 
hello world

4. Shebang 机制

脚本第一行的 #!(称为 Shebang)用于告诉系统“使用哪个解释器执行脚本”,必须放在脚本开头,常见格式:

#!/bin/bash    # Bash 脚本(Linux 默认)
#!/usr/bin/python  # Python 脚本
#!/usr/bin/perl   # Perl 脚本
  • 若省略 Shebang,系统会用当前默认 Shell(通常是 Bash)执行,但推荐显式声明(避免环境差异)。

二、Shell 脚本的组成结构

一个标准的 Shell 脚本由“Shebang 头”“注释”“命令/逻辑”三部分组成,语法规则简洁清晰。

1. 脚本组成与语法规则

组成部分格式与说明
Shebang 头第一行,#!/bin/bash,指定解释器。
注释# 开头的行(#! 除外),用于说明脚本功能、作者、日期等(提高可读性)。
命令与逻辑一行一条命令;一行多条命令用 ; 分隔;长命令用 \ 换行(避免行过长)。
示例:标准脚本结构
[root@ansible ~]# vim test1.sh
#!/bin/bash
# 脚本名称:hello.sh
# 功能:输出问候信息
# 作者:zhang3
# 日期:2025-09-9# 单行命令
echo "Hello World!"# 一行多条命令(; 分隔)
name="zhang3"; echo "Hello, $name!"# 长命令换行(\ 分隔)
echo "当前系统信息:" && \
uname -r && \
cat /etc/redhat-release
执行脚本文件:
[root@ansible ~]# sh test1.sh 
Hello World!
Hello, zhang3!
当前系统信息:
5.14.0-284.11.1.el9_2.x86_64
Red Hat Enterprise Linux release 9.2 (Plow)

2. 程序返回值

脚本执行后会产生两个结果:执行结果(如 echo 输出的内容)和状态返回码(判断脚本是否执行成功状态返回码变量:$?)。

状态返回码规则(0-255)
返回码含义
0脚本执行成功(所有命令均正常完成)。
1-255脚本执行失败(如命令不存在、权限不足、语法错误等),不同错误对应不同返回码。
查看返回码

执行脚本后,通过 echo $? 查看上一个命令/脚本的返回码:

# 执行成功的脚本
[root@ansible ~]# sh test.sh 
hello world
[root@ansible ~]# echo $?
0# 执行失败的脚本(如不存在的命令)
vim test3.sh
#!/bin/bash
nonexistent_cmd  # 不存在的命令
EOF
sh error.sh
echo $?  # 输出:127(命令未找到)
执行脚本文件:
[root@ansible ~]# sh test3.sh 
error.sh: line 2: nonexistent_cmd: command not found
127

三、Shell 脚本调试

脚本编写过程中难免出现语法错误或逻辑问题,需通过调试工具定位问题。

1. 脚本执行原理

Shell 执行脚本的流程:

  1. 加载环境变量:查找 ENV 变量指定的环境文件(如 /etc/profile~/.bashrc);
  2. 逐行执行脚本:从上至下、从左至右执行,遇到子脚本(嵌套脚本)先执行子脚本,再返回父脚本;
  3. 派生子进程:Shell 不直接执行命令,而是创建子进程执行(避免命令错误影响 Shell 主进程)。

2. 脚本编写注意事项

注意事项说明
开头加 Shebang必须写 #!/bin/bash,避免环境差异。
缩进与注释用 4 个空格缩进(逻辑控制块如 if/for),多写注释说明功能。
命名规范变量名大写(如 NAME)、局部变量小写(如 local age)、函数名小写(如 get_info)。
变量作用域默认变量为全局,函数内用 local 声明局部变量(避免污染全局)。
调试辅助命令set -e:遇到命令返回非 0 时退出脚本(避免错误扩散);
set -x:打印执行过程(每行命令执行前显示)。
路径与测试命令用绝对路径(如 /bin/ls 而非 ls);脚本先在测试环境运行,再部署到生产。
命令引用引用命令结果用反引号 `cmd`$(cmd)(推荐 $(cmd),兼容性更好)。

3. 脚本调试方法

核心通过 bash 命令的选项调试,常用选项:

调试选项语法格式功能说明
-nbash -n a.sh检查脚本语法错误(不执行脚本),若无输出则语法正确。
-xbash -x a.sh单步执行脚本,打印每一行命令的执行过程(含变量展开结果),定位逻辑错误。
示例:调试脚本
# 创建有逻辑错误的脚本(计算两数之和,但变量名错误)
cat > calc.sh << EOF
#!/bin/bash
a=10
b=20
sum=\$((a + c))  # 错误:变量 c 未定义
echo "sum: \$sum"
EOF# 1. 检查语法错误(无输出,语法正确)
[root@ansible ~]# bash -n calc.sh# 2. 调试执行(查看变量展开过程)
[root@ansible ~]# bash -x calc.sh
+ a=10
+ b=20
+ sum=10
+ echo 'sum: 10'
sum: 10
# (通过输出发现 sum 计算时用了未定义的 c,定位错误)
执行脚本文件:
[root@ansible ~]# sh calc.sh 
sum: 10

4. 实战案例:文件与目录管理脚本

需求:完成以下自动化操作,并用调试工具验证:

  1. 创建目录 /tmp/chenyu
  2. 切换到该目录;
  3. 创建目录 a1cb2d6hina
  4. 创建空文件 xyx123y123
  5. 列出以 a6 开头的文件/目录,写入 /tmp/file1
  6. 列出以字母开头、后跟 1 个数字、再跟任意字符的文件/目录,写入 /tmp/file2
脚本实现(file_manage.sh
[root@ansible ~]# vim file_manage.sh#!/bin/bash
# 功能:自动化管理 /tmp/chenyu 下的文件与目录
set -x  # 开启调试,打印执行过程# 1. 创建目录并切换
mkdir -p /tmp/zhang3  # -p 确保目录不存在时创建
cd /tmp/zhang3# 2. 创建目录
mkdir -p a1c b2d 6hina# 3. 创建空文件
touch xy x123y 123# 4. 筛选以 a 或 6 开头的文件/目录,写入 /tmp/file1
ls -d [a6]* > /tmp/file1  # [a6]* 匹配以 a 或 6 开头的内容# 5. 筛选“字母开头+1个数字+任意字符”的文件/目录,写入 /tmp/file2
ls -d [[:alpha:]][[:digit:]]* > /tmp/file2  # [[:alpha:]] 匹配字母,[[:digit:]] 匹配数字set +x  # 关闭调试
echo "脚本执行完成!"
执行与验证
# 1. 赋予权限并执行
[root@ansible ~]# chmod +x file_manage.sh
[root@ansible ~]# ./file_manage.sh# 2. 验证结果
[root@ansible ~]# cat /tmp/file1
6hina
a1c
[root@ansible ~]# cat /tmp/file2
a1c
b2d
x123y

四、Shell 运算符

Shell 原生不支持复杂运算,需通过 exprlet$((...)) 等工具实现,常见运算符分“算术运算”和“逻辑运算”。

1. 算术运算符

用于整数计算(浮点型需用 bc 工具),常用运算符与示例:

运算符描述实现方式与示例(a=10b=20
+加法val=$(expr $a + $b)val=$((a + b))(结果:30)
-减法val=$(expr $b - $a)val=$((b - a))(结果:10)
*乘法val=$(expr $a \* $b)(需转义 *)或 val=$((a * b))(结果:200)
/除法val=$(expr $b / $a)val=$((b / a))(结果:2)
%取余val=$(expr $b % $a)val=$((b % a))(结果:0)
=赋值a=20(将 20 赋值给变量 a
==相等判断if [ $a == $b ]; then ...(判断 ab 是否相等)
!=不相等判断if [ $a != $b ]; then ...(判断 ab 是否不相等)

示例:

[root@ansible ~]# vim test5.sh#!/bin/bash
a=10
b=20
val=`expr $a + $b`
echo "a + b = $val"[root@ansible ~]# sh test5.sh 
a + b = 30

文章转载自:

http://7BKTCgK9.txmLg.cn
http://KYLtzy9Z.txmLg.cn
http://iO6R1iGF.txmLg.cn
http://MdG05GkI.txmLg.cn
http://AUoM9OZm.txmLg.cn
http://kv970epb.txmLg.cn
http://2SEuroi8.txmLg.cn
http://agAb8lkf.txmLg.cn
http://MZgxzkg6.txmLg.cn
http://uJqRebqR.txmLg.cn
http://pumlqQQ0.txmLg.cn
http://wGbylgSv.txmLg.cn
http://BIsMNyvd.txmLg.cn
http://BPsA6LJI.txmLg.cn
http://OZ5ifVl7.txmLg.cn
http://olOPTy2z.txmLg.cn
http://fVMwxB8p.txmLg.cn
http://R2wjwFnZ.txmLg.cn
http://pDP2pwMn.txmLg.cn
http://oJEDhtFa.txmLg.cn
http://upTLJC5e.txmLg.cn
http://g8ScK7c5.txmLg.cn
http://eNycjXbm.txmLg.cn
http://flKdtlNw.txmLg.cn
http://8UtQPyEI.txmLg.cn
http://2iW6Vr12.txmLg.cn
http://mNadHpWr.txmLg.cn
http://PGcSqAyQ.txmLg.cn
http://4E7Voo9M.txmLg.cn
http://yG5Docdm.txmLg.cn
http://www.dtcms.com/a/375841.html

相关文章:

  • Nginx如何部署HTTP/3
  • 解一元三次方程
  • A股大盘数据-20250909分析
  • 05-Redis 命令行客户端(redis-cli)实操指南:从连接到返回值解析
  • shell函数+数组+运算+符号+交互
  • 群晖Lucky套件高级玩法-——更新证书同步更新群晖自带证书
  • 照明控制设备工程量计算 -图形识别超方便
  • Matlab通过FFT快速傅里叶变换提取频率
  • iis 高可用
  • 有趣的数学 贝塞尔曲线和毕加索
  • 基于STM32的智能宠物小屋设计
  • STM32之RS485与ModBus详解
  • DCDC输出
  • GitHub 项目提交完整流程(含常见问题与解决办法)
  • Day39 SQLite数据库操作与文本数据导入
  • python常用命令
  • 广东省省考备考(第九十五天9.9)——言语、资料分析、判断推理(强化训练)
  • MySQL问题8
  • 【AI】Jupyterlab中关于TensorFlow版本问题
  • Java 运行时异常与编译时异常以及异常是否会对数据库造成影响?
  • CosyVoice2简介
  • 新机快速搭建java开发环境过程记录
  • std::enable_shared_from_this
  • Spring Boot--Bean的扫描和注册
  • Pytorch基础入门3
  • ARM-指令集全解析:从基础到高阶应用
  • ARM 汇编学习
  • 今天继续昨天的正则表达式进行学习
  • Mysql集群——MHA高可用架构
  • 【一包通刷】晶晨S905L(B)/S905L2(B)/S905L3(B)-原机安卓4升级安卓7/安卓9-通刷包