对于刚接触 Linux 或 Unix 系统的开发者来说,Shell 脚本往往是自动化操作的第一道门槛。它不像 Python 那样语法简洁,也不像 Java 那样有完善的面向对象体系,但却能以极少的代码实现强大的系统管理功能。本文将从 Shell 的基本概念讲起,带你一步步掌握脚本编写的核心基础,完成从 “手动操作” 到 “自动化脚本” 的跨越。

一、认识 Shell:什么是 Shell,为什么需要它?

简单来说,Shell 是用户与操作系统内核之间的 “翻译官”—— 它接收用户输入的命令,传递给内核执行,并将结果返回给用户。我们在终端中输入的ls、cd、mkdir等命令,都是通过 Shell 解析执行的。

常见的 Shell 类型

不同的操作系统默认搭载的 Shell 可能不同,常见的有:

  • bash:Linux 系统中最常用的 Shell,兼容 sh,支持丰富的扩展功能(如命令补全、历史记录);
  • zsh:功能更强大的 Shell,支持更多主题和插件,是很多开发者的个性化选择;
  • sh:早期的 Bourne Shell,语法简单但功能有限,现在多被 bash 兼容替代。

在终端中输入echo $SHELL可以查看当前使用的 Shell,本文将以最通用的bash为例进行讲解。

为什么要学 Shell 编程?

想象以下场景:

  • 每天需要手动备份 10 个目录的日志文件;
  • 批量修改 100 个文件的命名格式;
  • 定期检查服务器的磁盘使用率并发送告警。

这些重复劳动如果用 Shell 脚本实现自动化,能节省大量时间。Shell 脚本的核心价值在于 “批量执行命令 + 逻辑控制”,它能将一系列命令按顺序组织,并通过条件判断、循环等逻辑实现复杂任务。

二、第一个 Shell 脚本:Hello World 的诞生

编写 Shell 脚本的流程非常简单,只需三个步骤:创建文件→编写代码→赋予权限并执行。

1. 创建脚本文件

用任意文本编辑器(如 vim、nano)创建一个.sh后缀的文件,例如hello.sh:


vim hello.sh

2. 编写脚本内容

在文件中输入以下代码:


#!/bin/bash# 这是我的第一个Shell脚本echo "Hello, Shell Programming!"

代码解析:

  • #!/bin/bash:称为 “shebang”,必须放在脚本第一行,指定脚本由 bash 解释执行;
  • # 这是注释:#开头的行是注释,用于说明代码功能,不被执行;
  • echo "...":打印字符串到终端,类似其他语言的print函数。

3. 赋予执行权限并运行

刚创建的脚本默认没有执行权限,需要用chmod命令赋予:


chmod +x hello.sh # 赋予执行权限

然后执行脚本:


./hello.sh # 输出:Hello, Shell Programming!

也可以直接通过 bash 命令运行(无需执行权限):


bash hello.sh # 同样生效

小技巧:如果脚本放在/usr/local/bin等环境变量目录下,可直接输入文件名执行(如hello.sh),无需带路径。

三、Shell 变量:存储数据的容器

和其他编程语言一样,Shell 也需要变量来存储数据。但与 Python 等语言不同,Shell 变量的定义和使用有其独特性。

1. 变量的定义与赋值

定义变量的格式为变量名=值,注意等号两边不能有空格


name="Alice" # 正确:字符串赋值age=25 # 正确:数字赋值# 错误写法:name = "Bob"(等号两边有空格)

2. 变量的使用

使用变量时需在变量名前加$符号,例如:


#!/bin/bashname="Alice"echo "My name is $name" # 输出:My name is Aliceecho "Age: $age" # 输出:Age: (未定义的变量会被视为空)

如果变量名与其他字符相邻,可用大括号{}区分:


echo "Hello, ${name}123" # 输出:Hello, Alice123(若不加{}会被解析为$name123)

3. 环境变量与局部变量

  • 局部变量:仅在当前脚本或终端中有效,如上面定义的name;
  • 环境变量:全局生效,可被所有子进程访问,常用的有:
    • $HOME:用户主目录(如/home/alice);
    • $PATH:命令搜索路径(存放可执行命令的目录);
    • $USER:当前登录用户名;
    • $?:上一条命令的退出状态(0 表示成功,非 0 表示失败)。

查看环境变量可用echo,例如:


echo $HOME # 输出:/home/aliceecho $PATH # 输出:/usr/local/sbin:/usr/local/bin:...

自定义环境变量需用export命令:


export WORK_DIR="/data/project" # 定义环境变量

四、数据类型:字符串与数字的处理

Shell 是弱类型语言,变量默认都按字符串处理,但也支持数字运算。

1. 字符串操作

字符串是 Shell 中最常用的数据类型,支持拼接、截取、替换等操作。

(1)字符串拼接

直接将变量或字符串放在一起即可:


first="Hello"last="World"full="$first $last" # 拼接为"Hello World"echo $full # 输出:Hello World
(2)字符串长度

用${#变量名}获取长度:


str="Shell"echo ${#str} # 输出:5("Shell"有5个字符)
(3)字符串截取

格式:${变量名:起始位置:长度}(起始位置从 0 开始):


path="/home/user/docs/file.txt"# 从第6个字符开始截取(跳过"/home/")echo ${path:6} # 输出:user/docs/file.txt# 从第6个字符开始,截取4个字符echo ${path:6:4} # 输出:user
(4)字符串替换
  • 替换第一个匹配项:${变量名/旧字符串/新字符串}
  • 替换所有匹配项:${变量名//旧字符串/新字符串}

示例:


filename="report_2023_v1.txt"# 替换第一个"_"为"-"echo ${filename/_/-} # 输出:report-2023_v1.txt# 替换所有"_"为"-"echo ${filename//_/-} # 输出:report-2023-v1.txt

2. 数字运算

Shell 默认将数字视为字符串,需用特殊语法进行运算,常用的有两种方式:

(1)$((表达式))

适合简单运算:


a=10b=3echo $((a + b)) # 输出:13echo $((a * b)) # 输出:30echo $((a / b)) # 输出:3(整数除法,向下取整)echo $((a % b)) # 输出:1(取余数)
(2)expr 命令

注意表达式中运算符两边需有空格:


expr 10 + 3 # 输出:13expr 10 \* 3 # 乘法需加转义符\(避免被Shell解析)

推荐使用$((...)),语法更简洁且支持变量直接参与运算。

五、输入输出与管道:数据的流转

Shell 脚本的输入输出控制和管道操作,是实现命令协作的核心。

1. 标准输入输出

默认情况下:

  • 标准输入(stdin):从键盘接收输入,文件描述符为 0;
  • 标准输出(stdout):输出到终端,文件描述符为 1;
  • 标准错误(stderr):错误信息输出到终端,文件描述符为 2。

2. 重定向:改变输入输出的方向

通过重定向符号可将输入输出指向文件:

  • >:覆盖写入文件(如echo "test" > file.txt);
  • >>:追加写入文件(如echo "test" >> file.txt);
  • <:从文件读取输入(如read var < file.txt);
  • 2>:将错误信息写入文件(如ls error_dir 2> err.log);
  • &>:将标准输出和错误都写入文件(如command &> output.log)。

示例:


# 将命令输出写入文件(覆盖原有内容)ls -l > file_list.txt# 追加输出到文件echo "新内容" >> file_list.txt# 捕获错误信息rm non_exist_file 2> error.log

3. 管道:命令间的数据传递

管道符号|可将前一个命令的输出作为后一个命令的输入,实现命令协作:


# 查找包含"error"的日志行,并统计数量cat app.log | grep "error" | wc -l# 列出当前目录文件,按大小排序(逆序)ls -l | sort -k5,5nr

命令解析:

  • grep "error":筛选包含指定字符串的行;
  • wc -l:统计行数;
  • sort -k5,5nr:按第 5 列(文件大小)逆序(nr)排序。

六、实战案例:批量文件重命名脚本

掌握了基础语法后,我们来编写一个实用脚本:将指定目录下的所有.txt文件添加前缀(如2023_)。

脚本代码

​#!/bin/bash# 批量给txt文件添加前缀# 使用方法:./rename_txt.sh 目录路径 前缀# 检查参数是否正确if [ $# -ne 2 ]; thenecho "使用错误!正确用法:$0 目录路径 前缀"exit 1fidir=$1prefix=$2# 检查目录是否存在if [ ! -d "$dir" ]; thenecho "错误:目录 $dir 不存在!"exit 1fi# 切换到目标目录cd "$dir" || exit 1# 遍历txt文件并添加前缀for file in *.txt; do# 跳过非文件(如目录)if [ -f "$file" ]; thennew_name="${prefix}${file}"mv "$file" "$new_name"echo "已重命名:$file → $new_name"fidoneecho "批量重命名完成!"​

代码解析

  1. $#表示参数个数,$0表示脚本名,$1、$2表示第一个和第二个参数;
  1. [ -d "$dir" ]判断是否为目录,[ -f "$file" ]判断是否为文件(条件判断语法将在后续文章详细讲解);
  1. for file in *.txt遍历所有 txt 文件,mv命令执行重命名。

运行效果


# 创建测试文件mkdir test_dirtouch test_dir/{a,b,c}.txt# 执行脚本./rename_txt.sh test_dir 2023_# 输出结果已重命名:a.txt → 2023_a.txt已重命名:b.txt → 2023_b.txt已重命名:c.txt → 2023_c.txt

批量重命名完成!

七、总结

  • Shell 的作用与常见类型;
  • 脚本的创建、执行流程;
  • 变量定义、数据类型(字符串、数字);
  • 输入输出重定向与管道操作;
  • 一个实战案例(批量重命名文件)。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/bicheng/90207.shtml
繁体地址,请注明出处:http://hk.pswp.cn/bicheng/90207.shtml
英文地址,请注明出处:http://en.pswp.cn/bicheng/90207.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

混合遗传粒子群算法在光伏系统MPPT中的应用研究

混合遗传粒子群算法在光伏系统MPPT中的应用研究 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家&#xff0c;觉得好请收藏。点击跳转到网站。 摘要 本文针对光伏系统最大功率点跟踪(MPPT)问题&#xff0…

机器视觉的布料丝印应用

在纺织印染行业&#xff0c;布料丝印工艺的精度直接决定产品外观质量与市场竞争力。传统丝印设备依赖机械定位与人工校准&#xff0c;面对高密度图案、柔性面料或复杂纹理时&#xff0c;易出现套色偏移、油墨渗透不均等问题&#xff0c;导致良品率波动与生产成本攀升。 随着机…

前端常用类库

常用类库 类库作用 类库可以帮助我们快速实现项目业务的开发与功能的实现, 帮助我们解放劳动力提高生产效率, 前端中的类库与框架都是由原生javascript编写, 提供给其他开发者应用于某一业务环境或者需求。一般有开发者/团队开源维护. 优秀的类库需要具备高度封装可用, 稳定, …

通俗易懂循环神经网络(RNN)指南

本文用直观类比、图表和代码&#xff0c;带你轻松理解RNN及其变体&#xff08;LSTM、GRU、双向RNN&#xff09;的原理和应用。什么是循环神经网络 循环神经网络&#xff08;Recurrent Neural Network, RNN&#xff09;是一类专门用于处理序列数据的神经网络。与前馈神经网络不同…

【SVM】支持向量机实例合集

基于Java的SVM(支持向量机)实例合集 以下是一个基于Java的SVM(支持向量机)实例合集,包含核心代码示例和应用场景说明。这些例子基于流行的机器学习库(如LIBSVM、Weka、JSAT)实现。 数据准备与加载 使用LIBSVM格式加载数据集: // 加载LIBSVM格式数据 svm_problem pr…

Python100个库分享第38个—lxml(爬虫篇)

目录专栏导读&#x1f4da; 库简介&#x1f3af; 主要特点&#x1f6e0;️ 安装方法Windows安装Linux/macOS安装验证安装&#x1f680; 快速入门基本使用流程HTML vs XML解析&#x1f50d; 核心功能详解1. XPath选择器2. CSS选择器支持3. 元素操作&#x1f577;️ 实战爬虫案例…

imx6ull-系统移植篇17——linux顶层 Makefile(上)

目录 前言 顶层 Makefile 源码简析 版本号 MAKEFLAGS 变量 命令输出 静默输出 设置编译结果输出目录 代码检查 模块编译 设置目标架构和交叉编译器 调用 scripts/Kbuild.include 文件 交叉编译工具变量设置 头文件路径变量 导出变量 make xxx_defconfig 过程 …

OpenCV 官翻6 - Computational Photography

文章目录图像去噪目标理论OpenCV中的图像去噪1、cv.fastNlMeansDenoisingColored()2、cv.fastNlMeansDenoisingMulti()附加资源图像修复目标基础概念代码补充资源练习高动态范围成像&#xff08;HDR&#xff09;目标理论基础曝光序列HDR1、将曝光图像加载到列表中2、将曝光序列…

APT32F1732RBT8爱普特微电子 32位MCU国产芯片 智能家居/工业控制 首选

APT32F1732RBT8 爱普特微电子&#xff0c;32位MCU国产芯片一、产品简介APT32F1732RBT8 是爱普特微电子&#xff08;APT&#xff09;推出的高性能32位ARM Cortex-M0内核MCU&#xff0c;主频高达48MHz&#xff0c;内置64KB Flash8KB RAM&#xff0c;专为智能家居、工业控制、消费…

Smart Tomcat

本篇博客的内容是教你借助idea中的插件,把tomcat集成到idea中安装 Smart Tomcat 插件搜索下载 ,如果一直处于加载界面,就尝试一下科学上网配置 Smart Tomcat 插件 点击右上角的 "Add Configuration"选择左侧的 "Smart Tomcat" 在 Name 这一栏填写一个名字(…

Linux_shell编写

title: Linux_4 shell编写 shell pwd (/root/A/2025_7/19/myshell) 首先需要设计命令行提示 &#xff08;MakeCommandLine()&#xff09; 首先获取相关信息 getenv(“name”) // 获取用户名 const char* GetUserName() {const char* name getenv("USER");if (name …

【数据结构】栈的深入解析--用C语言实现

文章目录1.栈的概念2.栈的底层结构3.栈的功能4.栈的实现4.1.栈结构的定义4.2.栈的初始化4.3.栈的销毁4.4.入栈4.5.出栈4.6.取栈顶元素4.7.获取栈中有效元素个数5.完整代码Stack.hStack.cmain.c运行结果1.栈的概念 是一种特殊的线性表&#xff0c;只允许数据在固定的一段进行插…

Git仓库核心概念与工作流程详解:从入门到精通

Git仓库的基本概念版本库&#xff08;Repository&#xff09;是Git的核心概念&#xff0c;你可以简单理解为一个被Git管理的目录。这个目录里的所有文件都能被Git跟踪&#xff0c;记录每次修改和删除&#xff0c;让你可以随时追溯历史或在未来某个时刻"还原"文件。Gi…

Web开发 05

1 React库&#xff08;人话详解版&#xff09;别慌&#xff0c;React 刚接触时是会有点懵&#xff0c;咱们用 “人话 类比” 一步步拆&#xff1a;核心概念先抓牢组件&#xff08;Component&#xff09;把它想成 “乐高积木”&#xff0c;比如做个社交 App&#xff0c;顶部导航…

RustDesk 自建中继服务器教程(Mac mini)

&#x1f4d6; 教程目标 在家里的 Mac mini 上部署 RustDesk 中继服务器 (hbbs hbbr)&#xff0c;让你从办公室、笔电或手机 低延迟、安全 地远程控制家里的 Windows 和 Mac mini。 ✅ 不依赖第三方服务器 ✅ 支持 P2P 和中继双模式 ✅ 全流量可控、跨平台 &#x1f3d7;️ 架…

数据库—修改某字段默认值

前言有时候&#xff0c;数据库的字段默认值没有正确设置&#xff0c;这时候需要改默认值。以下是我做的改默认值的记录&#xff0c;希望对网友有所帮助。1.SQL SERVER下面的示例假设你要修改名为 YourColumnName 的字段&#xff0c;并为其设置一个新的默认值 NewDefaultValue。…

Spring快速整合Mybatis

MyBatis是一个优秀的持久层框架&#xff0c;Spring则是广泛使用的Java应用框架。可以将两者整合可以充分发挥各自的优势。 1、Spring整合MyBatis的基本配置 添加依赖&#xff1a; <dependency><groupId>org.springframework</groupId><artifactId>spri…

基于深度学习的语音识别:从音频信号到文本转录

前言 语音识别&#xff08;Automatic Speech Recognition, ASR&#xff09;是人工智能领域中一个极具挑战性和应用前景的研究方向。它通过将语音信号转换为文本&#xff0c;为人们提供了更加自然和便捷的人机交互方式。近年来&#xff0c;深度学习技术在语音识别领域取得了显著…

本地部署Nacos开源服务平台,并简单操作实现外部访问,Windows 版本

Nacos 是一款阿里开源的动态服务发现、配置、管理平台&#xff0c;拥有易于集成、高可用与可扩展等特点。它提供了动态服务注册和发现能力&#xff0c;使得服务自动注册到服务器并且消费真能够发现提供者。本文将详细介绍如何在本地安装 Nacos &#xff0c;以及结合nat123端口映…

数据结构:反转字符串(Reversing a String)

目录 方法一&#xff1a;双指针法 方法二&#xff1a;辅助数组 方法对比总结&#xff1a; 问题定义 给定一个字符串&#xff0c;例如&#xff1a; char str[] "hello";我们的目标是把它反转成&#xff1a; "olleh"&#x1f4cc; 输入特点&#xff…