Shell 编程基础入门从认识到实战

发布于:2025-07-22 ⋅ 阅读:(17) ⋅ 点赞:(0)

对于刚接触 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/bash

name="Alice"

echo "My name is $name" # 输出:My name is Alice

echo "Age: $age" # 输出:Age: (未定义的变量会被视为空)

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


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

3. 环境变量与局部变量

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

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


echo $HOME # 输出:/home/alice

echo $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=10

b=3

echo $((a + b)) # 输出:13

echo $((a * b)) # 输出:30

echo $((a / b)) # 输出:3(整数除法,向下取整)

echo $((a % b)) # 输出:1(取余数)
(2)expr 命令

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


expr 10 + 3 # 输出:13

expr 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 ]; then

echo "使用错误!正确用法:$0 目录路径 前缀"

exit 1

fi

dir=$1

prefix=$2

# 检查目录是否存在

if [ ! -d "$dir" ]; then

echo "错误:目录 $dir 不存在!"

exit 1

fi

# 切换到目标目录

cd "$dir" || exit 1

# 遍历txt文件并添加前缀

for file in *.txt; do

# 跳过非文件(如目录)

if [ -f "$file" ]; then

new_name="${prefix}${file}"

mv "$file" "$new_name"

echo "已重命名:$file → $new_name"

fi

done

echo "批量重命名完成!"

​

代码解析

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

运行效果


# 创建测试文件

mkdir test_dir

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

网站公告

今日签到

点亮在社区的每一天
去签到