bash 基础编程的核心语法
shell 和 bash 的区别
什么是 “shell”?
“shell”(中文常译为 “壳”)是用户与操作系统内核(Kernel)之间的 “中间程序”,它的核心作用是:
- 接收用户输入的命令(比如ls查看文件、cd切换目录);
- 将命令翻译成内核能理解的语言,让内核执行操作;
- 再将内核的执行结果返回给用户。
简单说,shell 就是 “用户操作内核的桥梁”。没有 shell,用户无法直接与内核交互(比如你在终端敲的所有命令,都需要 shell 来解析执行)。
“bash” 是什么?
“bash” 的全称是 “Bourne Again SHell”(“再一次的 Bourne 壳”),它是众多 shell 实现中的一种,由 GNU 组织开发,诞生于 1989 年,目的是替代早期的 Bourne shell(sh,1979 年推出的第一个主流 shell)。
bash 的特点是:
- 兼容性强:完全兼容 Bourne shell(sh)的语法,老的 sh 脚本可以直接在 bash 中运行;
- 功能丰富:在 sh 的基础上增加了很多实用功能(比如数组、函数、更灵活的条件判断、命令补全等);
- 应用广泛:目前几乎所有 Linux 发行版(如 Ubuntu、CentOS)、macOS(默认 shell,不过最新版本可能切换为 zsh,但仍支持 bash)都将 bash 作为默认 shell,是最主流的 shell 实现。
区别
概念 | 本质 | 包含关系 | 典型应用 |
---|---|---|---|
shell | 命令行解释器的统称(类别) | 包含 bash、zsh、ksh 等 | 作为用户与内核的交互接口 |
bash | shell 的一种具体实现(实例)全称 Bourne Again SHell,shell 的主流实现 | 是 shell 的子集,最常用的一种 | 作为默认 shell,执行 shell 脚本 |
shell 脚本 | 用 shell 语法编写的自动化脚本 | 可由 bash、zsh 等多种 shell 执行 | 批量处理、自动化任务等 |
bash 脚本 | 用 bash 语法编写的.sh文件 | 自动化执行命令(批量处理、定时任务等) | 本质是 “命令的组合与逻辑控制” |
- 当我们说 “写 shell 脚本” 时,90% 以上的场景其实是 “写 bash 脚本”(因为 bash 最常用);而 “bash 编程” 就是用 bash 的语法规则来编写这类脚本,实现命令的自动化组合。
- zsh(macOS 新默认 shell),它们的基础语法和 bash 很像(因为都兼容 sh),但增加了各自的扩展功能 —— 但核心逻辑仍属于 “shell 编程” 的范畴。
bash 基础编程的核心语法
核心语法模块
1. 变量操作(基础中的基础)
核心语法
- 赋值:变量名=值(等号两侧无空格,踩坑重灾区)
- 使用:$变量名 或 ${变量名}(加{}避免歧义,如${name}123)
- 只读变量:readonly 变量名(赋值后无法修改)
- 删除变量:unset 变量名(删除后变量值为空)
- 值为字符串:字符串可以用单引号,也可以用双引号,也可以不用引号
字符串特殊操作
需求 | 语法示例 | 结果(假设name=“test”) |
---|---|---|
取字符串长度 | ${#name} | 4 |
截取子串(从索引 0 开始) | ${name:1:2}(从 1 取 2 个) | es |
单引号(原样输出) | echo ‘${name}’ | ${name}(不解析变量) |
双引号(解析变量) | echo “${name}” | test(解析变量值) |
- 示例
count=1 # 正确赋值(无空格) name="test" # 双引号解析变量(若有空格需用双引号,如name="my test") echo ${count} # 输出1 echo ${#name}; # 4 字符串长度 echo ${name:1:2}; # es 从第1个字符开始,取2个字符 echo "------- ${name} -----------"; # ------- test ----------- readonly count # 设为只读,后续count=2会报错 unset name # 删除name,echo $name输出空 DATE1=`date`; DATE2=`date +%Y-%m-%d`; echo $DATE1; # 2025年10月17日 星期五 16时52分01秒 CST echo $DATE2; # 2025-10-17
2. 数组操作(批量数据处理)
核心语法
- 定义数组:数组名=(元素1 元素2 元素3)(元素用空格分隔)
- 取单个元素:${数组名[索引]}(索引从 0 开始)
- 取所有元素:${数组名[*]} 或 ${数组名[@]}(双引号下@更安全,元素含空格时不拆分)
- 数组长度:${#数组名[@]}(同字符串长度语法)
示例
arr=(10 20 30 "hello bash") # 含空格元素需用双引号
echo ${arr[0]} # 输出10(第一个元素)
echo ${arr[*]} # 输出10 20 30 hello bash(所有元素)
echo ${arr[@]} # 输出10 20 30 hello bash(所有元素)
echo ${#arr[@]} # 输出4(数组长度)
# 遍历数组(推荐用@,兼容含空格元素)
for val in "${arr[@]}"; doecho "元素:$val"
done
3. 脚本参数传递(运行时传值)
核心变量(运行脚本时用:./test.sh 参数1 参数2)
变量 | 含义 | 示例(./test.sh 10 20) |
---|---|---|
$0 | 脚本自身路径 / 文件名 | ./test.sh |
1−1-1−n | 第 1 到第 n 个参数 | 参数1 $1=10,参数2 $2=20 |
$# | 参数总数 | 2 |
$* | 所有参数(视为单个字符串) | 10 20 |
$@ | 所有参数(视为独立字符串) | 10 20(遍历更安全) |
示例
# 脚本内容(test.sh)
echo "脚本名:$0"
echo "参数总数:$#"
echo "第一个参数:$1"
echo "所有参数:$@"# 运行脚本:./test.sh 5 8
# 输出:
# 脚本名:./test.sh
# 参数总数:2
# 第一个参数:5
# 所有参数:5 8
4. 运算符
-
支持多种运算符,包括:
-
算数运算符
- 条件表达式要放在方括号之间,并且要有空格,例如:
# [ "\$a"=="\$b" ]是错误的,必须写成 [ "\$a" == "\$b" ] a=1; b=2 if [ "$a"=="$b" ]; then d="true"; else d="false"; fi echo $d # 输出 true(错误,虽然1≠2,但被当作非空字符串判断) # == 前后无空格 此时 bash 会将 "$a"=="$b" 整体视为一个单一字符串 # 判断逻辑变成:“这个字符串是否非空”(因为 [ ] 中单独的字符串会被判断为 “非空即真”)
- 条件表达式要放在方括号之间,并且要有空格,例如:
-
关系运算符
-
布尔运算符
-
字符串运算符
-
文件测试运算符
原生bash不支持简单的数学运算,但是可以通过其他命令来实现,例如 awk 和 expr,expr 最常用。
- expr 是一款表达式计算工具,使用它能完成表达式的求值操作。
算术运算符
运算符 | 说明 |
---|---|
+ | 加法 |
- | 减法 |
* | 乘法 |
/ | 除法 |
% | 取余 |
= | 赋值 |
== | 相等,比较两个数字,相同返回true; |
!= | 不相等,比较两个数字,不相同返回true; |
total=`expr 3 + 2`
echo "参数总和为:$total" # 5
total2=`expr 5 - 2`
echo "参数差为:$total2" # 3
total3=`expr 5 \* 2`
echo "参数积为:$total3" # 10
total4=`expr 5 / 2`
echo "参数商为:$total4" # 2
total5=`expr 5 % 2`
echo "参数余为:$total5" # 1a=1
b=2
c=1
# 判断 a 是否等于 b,将结果(true/false)赋值给 d
if [ "$a" == "$b" ]; thend="true"
elsed="false"
fiecho "a == b ? $d" # 输出:a == b ? false# 同理判断 a 和 c(相等)
if [ "$a" == "$c" ]; thene="true"
elsee="false"
fiecho "a == c ? $e" # 输出:a == c ? true# 判断 a 是否不等于 b,将结果(true/false)赋值给 d
if [ "$a" != "$b" ]; thend="true"
elsed="false"
fi# 同理判断 a 和 c(是否不相等)
if [ "$a" != "$c" ]; thene="true"
elsee="false"
fiecho "a == b ? $d" # 输出:a == b ? true
echo "a == c ? $e" # 输出:a == c ? false
关系运算符
- 关系运算符只支持数字,不支持字符串,除非字符串的值是数字。
- 六个关系运算符
# -eq
if [ $a -eq $c ]
thenecho " $a -eq $c: 检测两个数是否相等,相等返回 true"
elseecho "$a -eq $c: 检测两个数是否相等,不相等返回 false"
fi
# -ne
if [ $a -ne $b ]
thenecho "$a -ne $b: 检测两个数是否不相等,不相等返回 true"
elseecho "$a -ne $b : 检测两个数是否不相等,相等返回 false"
fi
# -gt
if [ $b -gt $a ]
thenecho "$b -gt $a: 检测左边的数是否大于右边的数,大于返回 true"
elseecho "$b -gt $a: 检测左边的数是否大于右边的数,不大于返回 false"
fi
# -lt
if [ $a -lt $b ]
thenecho "$a -lt $b: 检测左边的数是否小于右边的数,小于返回 true"
elseecho "$a -lt $b: 检测左边的数是否小于右边的数,不小于返回 false"
fi
# -ge
if [ $b -ge $a ]
thenecho "$b -ge $a: 检测左边的数是否大于等于右边的数,大于等于返回 true"
elseecho "$b -ge $a: 检测左边的数是否大于等于右边的数,不大于等于返回 false"
fi
# -le
if [ $a -le $b ]
thenecho "$a -le $b: 检测左边的数是否小于等于右边的数,小于等于返回 true"
elseecho "$a -le $b: 检测左边的数是否小于等于右边的数,不小于等于返回 false"
fi
累了,先这样吧~