重生之我拿捏Linux——《三、shell脚本使用》
上一章咱们搞定了权限控制,这一章直接解锁 Linux 自动化的“核心技能”——Shell 脚本!不管是批量处理文件,还是定时执行系统任务,掌握 Shell 脚本都能让你从“重复敲命令”的困境中解放出来,真正实现“一次编写,多次复用”。今天就从语法基础到实战案例,带你吃透 Shell 脚本的用法!
一、bash语法
1. 脚本头部声明
- 作用:指定脚本解释器,必须放在脚本第一行
- 语法:
#!/bin/bash
(表示使用bash
解释器执行脚本,而非默认的sh
)
2. 变量
- 定义:
变量名=值
(等号前后无空格)例:name="Bash学习者"
、version=5.1
- 使用:
$变量名
或${变量名}
(加花括号避免歧义)例:echo "欢迎你,$name"
、echo "第${i}个元素"
- 命令替换:将命令结果赋值给变量,两种语法
变量=$(命令)
(推荐):current_dir=$(pwd)
变量=
命令(反引号):`date=`date +%F
- 局部变量:在函数内用
local
声明,仅函数内有效例:local name=$1
3. 环境变量
- 定义:系统预定义的变量,全大写字母,全局有效
- 常用环境变量:
$USER
:当前用户名$HOME
:用户家目录$PATH
:可执行程序的搜索路径$PWD
:当前工作目录$?
:上一条命令的退出状态(0 为成功,非 0 为失败)
4. 位置参数
- 定义:脚本运行时传入的参数,用
$n
表示(n 为数字) - 常用参数变量:
$0
:脚本自身的文件名$1~$9
:第 1 到第 9 个参数(超过 9 个用${10}
)$#
:参数的总个数$*
/$@
:所有参数($*
将参数视为整体,$@
视为独立个体)$?
:上一条命令的执行结果(0 成功,非 0 失败)
5. 条件判断
-
基本语法:
bash
if [ 条件表达式 ]; then命令 elif [ 条件表达式 ]; then命令 else命令 fi
(注意:
[ ]
前后必须有空格,条件表达式内部也要有空格) -
数值比较:
-eq
:等于([ 1 -eq 1 ]
)-ne
:不等于-lt
:小于(less than)-gt
:大于(greater than)-le
:小于等于-ge
:大于等于
-
字符串比较:
=
:等于([ "a" = "b" ]
)!=
:不等于-z
:字符串长度为 0(空字符串)-n
:字符串长度非 0
-
文件 / 目录判断:
-f 文件名
:是否为普通文件-d 目录名
:是否为目录-e 路径
:路径是否存在-r 路径
:是否有读权限-w 路径
:是否有写权限-x 路径
:是否有执行权限
6. 循环结构
for 循环
-
遍历列表:
bash
for 变量 in 列表; do命令 done
例:
for fruit in 苹果 香蕉 橙子; do echo $fruit; done
-
遍历数组:
bash
fruits=("苹果" "香蕉" "橙子") for fruit in "${fruits[@]}"; do # @表示所有元素,加引号避免空格分割问题echo $fruit done
-
数字范围:
bash
for i in {1..5}; do # 1到5的数字echo $i done
while 循环
- 语法:
bash
例:while [ 条件 ]; do命令(更新条件,避免死循环) done
bash
count=1 while [ $count -le 3 ]; doecho $countcount=$((count + 1)) # 数值自增 done
7. 函数
-
定义:
bash
函数名() {命令[return 退出码] # 可选,默认返回最后一条命令的状态 }
-
调用:
函数名 [参数]
例:greet "Bash学习者"
-
参数传递:函数内用
$1~$n
接收参数(同位置参数)例:bash
add() {echo $(( $1 + $2 )) # 通过echo返回计算结果 } result=$(add 10 20) # 调用并获取结果
-
返回值:
- 用
echo
输出结果(适合返回数据) - 用
return
返回退出码(0-255,适合判断成功 / 失败)
- 用
8. 输入输出重定向
-
标准输出重定向:
>
:覆盖写入文件(echo "内容" > file.txt
)>>
:追加写入文件(echo "内容" >> file.txt
)
-
标准错误重定向:
2>
:覆盖写入错误信息(command 2> error.log
)2>>
:追加写入错误信息
-
合并输出与错误:
&>
:同时重定向输出和错误(command &> all.log
)
9. 管道(Pipe)
- 语法:
命令1 | 命令2
- 将命令 1 的输出作为命令 2 的输入例:
ls -l | grep ".sh"
(筛选目录中.sh 文件)例:cat file.txt | wc -l
(统计文件行数)
- 将命令 1 的输出作为命令 2 的输入例:
10. 数组
-
定义:
数组名=(元素1 元素2 ...)
例:colors=("红色" "绿色" "蓝色")
-
访问元素:
${数组名[索引]}
(索引从 0 开始)例:${colors[1]}
(获取第二个元素 “绿色”) -
所有元素:
${数组名[@]}
或${数组名[*]}
例:echo "${colors[@]}"
-
数组长度:
${#数组名[@]}
例:echo "数组长度:${#colors[@]}"
11. 数值计算
- 语法:
$(( 表达式 ))
例:sum=$(( 10 + 20 ))
、count=$((count + 1))
支持+
、-
、*
、/
、%
(取余)等运算符
12. 注释
- 单行注释:
# 注释内容
(脚本中除了#!/bin/bash
外,#
后的内容均为注释)
二、具体实例
1. 变量定义与使用
# 定义变量(等号前后无空格)
name="Alice"
age=30# 使用变量($变量名 或 ${变量名})
echo "姓名:$name,年龄:${age}岁" # 输出:姓名:Alice,年龄:30岁# 命令替换(将命令结果存为变量)
current_time=$(date +"%H:%M:%S") # 推荐用$()
echo "当前时间:$current_time" # 输出:当前时间:15:30:45# 变量拼接
prefix="file_"
suffix=".txt"
filename="${prefix}001${suffix}"
echo $filename # 输出:file_001.txt
2. 环境变量与位置参数
# 环境变量(系统预定义)
echo "当前用户:$USER" # 输出:当前用户:your_username
echo "家目录:$HOME" # 输出:家目录:/home/your_username
echo "命令搜索路径:$PATH" # 输出:一堆目录(用冒号分隔)# 位置参数(运行脚本时传入的参数)
# 保存为 test.sh,执行:bash test.sh apple banana
echo "脚本名:$0" # 输出:脚本名:test.sh
echo "第一个参数:$1" # 输出:第一个参数:apple
echo "第二个参数:$2" # 输出:第二个参数:banana
echo "参数总数:$#" # 输出:参数总数:2
echo "所有参数:$@" # 输出:所有参数:apple banana
3. 条件判断(if 语句)
# 1. 判断文件是否存在
file="test.txt"
if [ -f "$file" ]; thenecho "$file 是普通文件"
elif [ -d "$file" ]; thenecho "$file 是目录"
elseecho "$file 不存在"
fi# 2. 数值比较
a=10
b=20
if [ $a -lt $b ]; then # -lt 表示小于echo "$a < $b" # 输出:10 < 20
fi# 3. 字符串比较
str1="hello"
str2="hello"
if [ "$str1" = "$str2" ]; then # = 表示等于(注意空格)echo "字符串相等"
elseecho "字符串不等"
fi
4. 循环结构
for 循环
# 1. 遍历列表
fruits=("苹果" "香蕉" "橙子")
for fruit in "${fruits[@]}"; do # @表示所有元素,加引号处理空格echo "我喜欢吃 $fruit"
done
# 输出:
# 我喜欢吃 苹果
# 我喜欢吃 香蕉
# 我喜欢吃 橙子# 2. 遍历数字范围
for i in {1..3}; do # 1到3的数字echo "计数:$i"
done
# 输出:
# 计数:1
# 计数:2
# 计数:3
while 循环
# 从1数到3
count=1
while [ $count -le 3 ]; do # -le 表示小于等于echo "while计数:$count"count=$((count + 1)) # 数值自增(等价于 count=$[count+1])
done
# 输出:
# while计数:1
# while计数:2
# while计数:3
5. 函数
# 1. 简单函数(无参数)
greet() {echo "你好!"
}
greet # 调用函数,输出:你好!# 2. 带参数的函数
add() {local sum=$(( $1 + $2 )) # local定义局部变量echo $sum # 通过echo返回结果
}
result=$(add 5 3) # 调用函数并获取结果
echo "5 + 3 = $result" # 输出:5 + 3 = 8# 3. 带返回值的函数(退出码)
check_file() {if [ -f "$1" ]; thenreturn 0 # 0表示成功elsereturn 1 # 非0表示失败fi
}
check_file "test.txt"
if [ $? -eq 0 ]; then # $?获取上一条命令的退出码echo "文件存在"
elseecho "文件不存在"
fi
6. 输入输出重定向与管道
# 1. 输出重定向(覆盖写入)
echo "这是一行内容" > output.txt # 写入到output.txt
cat output.txt # 查看文件,输出:这是一行内容# 2. 追加写入
echo "这是第二行内容" >> output.txt
cat output.txt
# 输出:
# 这是一行内容
# 这是第二行内容# 3. 管道(|):将前一个命令的输出作为后一个命令的输入
ls -l | grep ".sh" # 筛选当前目录下的.sh文件
cat output.txt | wc -l # 统计文件行数(输出:2)
7. 数组操作
# 定义数组
colors=("红" "绿" "蓝" "黄")# 访问单个元素(索引从0开始)
echo "第二个元素:${colors[1]}" # 输出:第二个元素:绿# 访问所有元素
echo "所有颜色:${colors[@]}" # 输出:所有颜色:红 绿 蓝 黄# 数组长度
echo "数组长度:${#colors[@]}" # 输出:数组长度:4# 修改元素
colors[2]="青" # 将第三个元素改为"青"
echo "修改后:${colors[@]}" # 输出:修改后:红 绿 青 黄
8. 数值计算
a=15
b=4# 加法
echo "$a + $b = $((a + b))" # 输出:15 + 4 = 19# 减法
echo "$a - $b = $((a - b))" # 输出:15 - 4 = 11# 乘法
echo "$a * $b = $((a * b))" # 输出:15 * 4 = 60# 除法(整数除法)
echo "$a / $b = $((a / b))" # 输出:15 / 4 = 3# 取余
echo "$a % $b = $((a % b))" # 输出:15 % 4 = 3
三、综合示例
#!/bin/bash
# 文件名: bash_learning.sh
# 描述: 一个用于学习bash脚本编程的示例脚本# 显示欢迎信息
echo "============================================="
echo " Bash脚本学习示例程序 "
echo "============================================="# ----------------------------
# 1. 变量定义与使用
# ----------------------------
echo -e "\n===== 1. 变量定义与使用 ====="
name="Bash学习者"
version=5.1
echo "欢迎你,$name!当前bash版本约为$version"# 命令替换:将命令结果赋值给变量
current_dir=$(pwd)
echo "当前工作目录: $current_dir"
echo "当前日期: $(date +%Y-%m-%d)"# ----------------------------
# 2. 环境变量
# ----------------------------
echo -e "\n===== 2. 环境变量 ====="
echo "你的用户名: $USER"
echo "你的家目录: $HOME"
echo "系统路径: $PATH"# ----------------------------
# 3. 位置参数
# ----------------------------
echo -e "\n===== 3. 位置参数 ====="
echo "脚本名称: $0"
echo "第一个参数: $1"
echo "第二个参数: $2"
echo "参数总数: $#"
echo "所有参数: $*"# ----------------------------
# 4. 条件判断
# ----------------------------
echo -e "\n===== 4. 条件判断 ====="# 检查文件是否存在
if [ -f "$0" ]; thenecho "脚本文件 $0 存在"
elseecho "脚本文件不存在"
fi# 数值比较
num1=10
num2=20
if [ $num1 -lt $num2 ]; thenecho "$num1 小于 $num2"
elif [ $num1 -gt $num2 ]; thenecho "$num1 大于 $num2"
elseecho "$num1 等于 $num2"
fi# 字符串比较
str1="hello"
str2="world"
if [ "$str1" = "$str2" ]; thenecho "字符串相等"
elseecho "字符串不相等: $str1 vs $str2"
fi# ----------------------------
# 5. 循环结构
# ----------------------------
echo -e "\n===== 5. 循环结构 ====="# for循环遍历列表
echo "for循环遍历列表:"
fruits=("苹果" "香蕉" "橙子" "葡萄")
for fruit in "${fruits[@]}"; doecho "水果: $fruit"
done# for循环数字范围
echo -e "\nfor循环数字范围:"
for i in {1..5}; doecho "计数: $i"
done# while循环
echo -e "\nwhile循环:"
count=1
while [ $count -le 3 ]; doecho "while计数: $count"count=$((count + 1)) # 数值计算
done# ----------------------------
# 6. 函数定义与调用
# ----------------------------
echo -e "\n===== 6. 函数 ====="# 定义函数
greet() {local name=$1 # 局部变量echo "你好,$name!"
}# 调用函数
greet "Bash学习者"# 带返回值的函数
add_numbers() {local a=$1local b=$2echo $((a + b)) # 通过echo返回结果
}result=$(add_numbers 15 25)
echo "15 + 25 = $result"# ----------------------------
# 7. 输入输出重定向
# ----------------------------
echo -e "\n===== 7. 输入输出重定向 ====="
echo "这行文字会被写入到临时文件中" > temp_learning.txt
echo "查看临时文件内容:"
cat temp_learning.txt# ----------------------------
# 8. 管道与过滤
# ----------------------------
echo -e "\n===== 8. 管道与过滤 ====="
echo "当前目录下的.sh文件:"
ls -l | grep "\.sh$"# ----------------------------
# 9. 数组
# ----------------------------
echo -e "\n===== 9. 数组 ====="
colors=("红色" "绿色" "蓝色")
echo "数组元素: ${colors[@]}"
echo "数组长度: ${#colors[@]}"
echo "第二个元素: ${colors[1]}"# ----------------------------
# 10. 结束与清理
# ----------------------------
echo -e "\n===== 10. 结束与清理 ====="
rm -f temp_learning.txt # 删除临时文件
echo "临时文件已清理"
echo -e "\n所有示例执行完毕!希望对你学习bash有所帮助!"
这一世,重生的你不再为批量处理发愁,你学会了如何使用脚本武装自己!