bash 详解:从基础到进阶的全面剖析
一、bash 的起源与发展
bash,全称 Bourne-Again SHell,是一种广泛使用的 Unix shell 和命令语言,它的发展历程与 Unix 系统的演进紧密相连。要了解 bash 的起源,就不得不提及 Unix 系统中早期的 shell 版本。
在 20 世纪 70 年代,Unix 系统诞生后,第一个重要的 shell 是由史蒂夫・伯恩(Stephen Bourne)开发的 Bourne shell(sh),它为用户与 Unix 系统的交互提供了便捷的命令行界面,奠定了现代 shell 的基础。然而,随着用户需求的不断增长,Bourne shell 在功能上逐渐显露出一些不足,例如缺乏命令行编辑、历史记录等实用功能。
为了弥补这些缺陷,1987 年,布莱恩・福克斯(Brian Fox)在 GNU 项目的支持下开发了 bash。bash 最初的设计目标是与 Bourne shell 保持兼容,同时整合其他 shell(如 C shell、Korn shell 等)的优秀特性,为用户提供更强大、更灵活的命令行环境。
自诞生以来,bash 不断发展完善。1996 年,bash 3.0 版本发布,引入了许多重要功能,如数组支持、更强大的模式匹配等;2009 年,bash 4.0 版本推出,增加了关联数组、大小写转换等新特性。如今,bash 已成为大多数 Linux 发行版和 macOS 系统默认的 shell,在 Unix 类操作系统中占据着举足轻重的地位,是系统管理员、开发者等进行日常工作和自动化任务的重要工具。
二、bash 的核心特性
(一)与 Bourne shell 兼容
bash 保持了与 Bourne shell 的高度兼容性,这意味着大多数为 Bourne shell 编写的脚本可以直接在 bash 中运行,无需修改或只需少量修改。这种兼容性确保了用户能够平滑过渡到 bash,同时保护了已有的脚本资源。
(二)命令行编辑功能
bash 提供了强大的命令行编辑功能,用户可以使用各种快捷键来编辑命令行,如左右箭头键移动光标、Backspace 键删除字符、Ctrl + A 移动到行首、Ctrl + E 移动到行尾等。此外,bash 还支持使用 vi 或 emacs 风格的编辑模式,用户可以根据自己的习惯进行设置。
(三)命令历史记录
bash 会记录用户输入的命令,用户可以通过上下箭头键浏览历史命令,按 Enter 键重新执行选中的命令。同时,用户还可以使用 history 命令查看所有历史记录,使用!n(n 为历史记录编号)重新执行第 n 条命令,使用!!重新执行上一条命令等,极大地提高了命令输入的效率。
(四)文件名扩展(通配符)
bash 支持多种通配符,用于匹配文件名,方便用户快速指定多个文件。常见的通配符包括:
- :匹配任意长度的任意字符(包括空字符)。例如,.txt 匹配所有以 .txt 结尾的文件。
- ?:匹配任意单个字符。例如,file?.txt 匹配 file1.txt、file2.txt 等,但不匹配 file12.txt。
- []:匹配指定范围内的任意单个字符。例如,[a-z].txt 匹配 a.txt、b.txt 等;[0-9].txt 匹配 1.txt、2.txt 等。
- [^]:匹配不在指定范围内的任意单个字符。例如,[^0-9].txt 匹配除了以数字开头且以 .txt 结尾的文件之外的其他符合条件的文件。
(五)管道与重定向
管道(|)和重定向是 bash 中非常重要的特性,它们允许用户将一个命令的输出作为另一个命令的输入,或者将命令的输出重定向到文件中,以及将文件的内容作为命令的输入。
- 管道:例如,ls -l | grep "txt" 表示将 ls -l 命令的输出作为 grep "txt" 命令的输入,用于查找当前目录下所有以 .txt 结尾的文件的详细信息。
- 输出重定向:> 用于将命令的输出重定向到文件中,会覆盖文件原有的内容;>> 用于将命令的输出追加到文件中,不会覆盖文件原有的内容。例如,echo "Hello World" > test.txt 将 "Hello World" 写入 test.txt 文件中;echo "Another line" >> test.txt 将 "Another line" 追加到 test.txt 文件中。
- 输入重定向:< 用于将文件的内容作为命令的输入。例如,sort < numbers.txt 表示对 numbers.txt 文件中的内容进行排序。
(六)变量与环境变量
bash 支持变量,变量可以存储字符串、数字等数据。用户可以自定义变量,也可以使用系统预设的环境变量。
- 自定义变量:变量的赋值格式为 变量名 = 值,例如 name="bash"。使用变量时,需要在变量名前加上 \(符号,例如 echo\)name 输出 bash。
- 环境变量:环境变量是在系统中具有全局作用的变量,用于配置系统环境。常见的环境变量包括 PATH(用于指定命令的搜索路径)、HOME(用户的主目录)、USER(当前用户名)等。可以使用 export 命令将自定义变量设置为环境变量,例如 export PATH=$PATH:/new/directory 将 /new/directory 目录添加到 PATH 环境变量中。
(七)函数
bash 允许用户定义函数,函数是一段可重复执行的命令序列,类似于其他编程语言中的函数。函数的定义格式如下:
函数名() {
命令序列
}
例如,定义一个输出欢迎信息的函数:
welcome() {
echo "Welcome to bash!"
}
调用函数时,直接使用函数名即可,如 welcome。
(八)控制结构
bash 提供了多种控制结构,用于控制脚本的执行流程,包括条件语句和循环语句。
- 条件语句:if...then...else...fi 用于根据条件执行不同的命令序列。例如:
if [ $1 -gt 10 ]; then
echo "The number is greater than 10."
else
echo "The number is less than or equal to 10."
fi
- 循环语句:for 循环用于遍历列表中的元素,while 循环用于在条件为真时重复执行命令序列。例如:
# for 循环
for i in 1 2 3 4 5; do
echo $i
done
# while 循环
count=1
while [ $count -le 5 ]; do
echo $count
count=$((count + 1))
done
三、bash 的语法结构
(一)变量
- 变量的定义与赋值
bash 中变量的定义和赋值非常简单,不需要声明类型,直接使用 变量名 = 值 的格式即可。例如:
name="Alice"
age=25
需要注意的是,变量名和等号之间不能有空格,否则会被解释为命令。
- 变量的引用
引用变量时,在变量名前加上 $ 符号。例如:
echo $name # 输出 Alice
echo "Age: $age" # 输出 Age: 25
在双引号中,变量会被替换为其值;在单引号中,变量不会被替换,原样输出。例如:
echo "$name" # 输出 Alice
echo '$name' # 输出 $name
- 变量的运算
bash 支持整数的算术运算,可以使用 $(()) 或 expr 命令。例如:
a=5
b=3
# 使用 $(( ))
sum=$((a + b))
echo $sum # 输出 8
# 使用 expr
product=$(expr $a \* $b) # 注意 * 前面需要加转义符 \
echo $product # 输出 15
- 数组
bash 支持一维数组,数组的定义方式为 数组名 =(元素 1 元素 2 ... 元素 n)。例如:
fruits=("apple" "banana" "orange")
访问数组元素时,使用 ${数组名 [索引]},索引从 0 开始。例如:
echo ${fruits[0]} # 输出 apple
echo ${fruits[1]} # 输出 banana
使用 \({数组名[@]} 可以获取数组中的所有元素,使用 \){# 数组名 [@]} 可以获取数组的长度。例如:
echo ${fruits[@]} # 输出 apple banana orange
echo ${#fruits[@]} # 输出 3
(二)运算符
- 算术运算符
bash 中的算术运算符包括 +(加)、-(减)、*(乘)、/(除)、%(取模)等,主要用于整数运算。例如:
x=10
y=4
echo $((x + y)) # 14
echo $((x - y)) # 6
echo $((x * y)) # 40
echo $((x / y)) # 2(整数除法,舍去小数部分)
echo $((x % y)) # 2
- 比较运算符
比较运算符主要用于条件判断,包括数值比较和字符串比较。
- 数值比较:
a=5
b=10
if [ $a -lt $b ]; then
echo "$a is less than $b"
fi
-
- -eq:等于
-
- -ne:不等于
-
- -gt:大于
-
- -lt:小于
-
- -ge:大于等于
-
- -le:小于等于
例如:
- 字符串比较:
str1="hello"
str2="world"
if [ $str1 != $str2 ]; then
echo "$str1 is not equal to $str2"
fi
-
- = 或 ==:等于
-
- !=:不等于
-
- -z:字符串长度为 0
-
- -n:字符串长度不为 0
例如:
- 逻辑运算符
bash 中的逻辑运算符包括:
- &&:逻辑与,当两个条件都为真时,结果为真。
- ||:逻辑或,当两个条件中有一个为真时,结果为真。
- !:逻辑非,取反条件的结果。
例如:
a=5
b=10
c=15
if [ $a -lt $b ] && [ $b -lt $c ]; then
echo "$a < $b < $c"
fi
(三)控制语句
- if 语句
if 语句的基本格式如下:
if 条件; then
命令序列
elif 条件; then
命令序列
else
命令序列
fi
例如,判断一个数是正数、负数还是零:
read num
if [ $num -gt 0 ]; then
echo "Positive number"
elif [ $num -lt 0 ]; then
echo "Negative number"
else
echo "Zero"
fi
- case 语句
case 语句用于多分支选择,基本格式如下:
case 变量 in
模式1)
命令序列
;;
模式2)
命令序列
;;
...
*)
命令序列
;;
esac
例如,根据输入的字符输出相应的信息:
read char
case $char in
[a-z])
echo "Lowercase letter"
;;
[A-Z])
echo "Uppercase letter"
;;
[0-9])
echo "Digit"
;;
*)
echo "Special character"
;;
esac
- for 循环
for 循环的基本格式有两种:
- 遍历列表中的元素:
for 变量 in 列表; do
命令序列
done
例如,遍历数组元素:
colors=("red" "green" "blue")
for color in ${colors[@]}; do
echo $color
done
- 类似 C 语言的 for 循环:
for ((初始化; 条件; 更新)); do
命令序列
done
例如,输出 1 到 5 的数字:
for ((i=1; i<=5; i++)); do
echo $i
done
- while 循环
while 循环的基本格式如下:
while 条件; do
命令序列
done
例如,不断读取用户输入,直到输入 "quit":
while true; do
read input
if [ $input = "quit" ]; then
break
fi
echo "You entered: $input"
done
- until 循环
until 循环与 while 循环相反,当条件为假时执行命令序列,直到条件为真时停止。基本格式如下:
until 条件; do
命令序列
done
例如,输出 1 到 5 的数字:
count=1
until [ $count -gt 5 ]; do
echo $count
count=$((count + 1))
done
- 跳转语句
- break:用于跳出当前循环。
- continue:用于跳过本次循环中剩余的命令,直接进入下一次循环。
例如,在循环中使用 break 和 continue:
# 使用 break
for i in 1 2 3 4 5; do
if [ $i -eq 3 ]; then
break
fi
echo $i
done
# 输出 1 2
# 使用 continue
for i in 1 2 3 4 5; do
if [ $i -eq 3 ]; then
continue
fi
echo $i
done
# 输出 1 2 4 5
(四)函数
- 函数的定义
bash 函数的定义有两种格式:
- 格式一:
函数名() {
命令序列
}
- 格式二:
function 函数名 {
命令序列
}
例如,定义一个计算两个数之和的函数:
add() {
sum=$(( $1 + $2 ))
echo $sum
}
- 函数的参数
在调用函数时,可以向函数传递参数,函数内部通过 \(1、\)2、...、\(n 来获取参数值,其中 \)1 表示第一个参数,\(2 表示第二个参数,以此类推。\)0 表示函数名,\(# 表示参数的个数,\)@ 表示所有参数的列表。例如:
greet() {
echo "Hello, $1! You have $# arguments."
echo "Arguments: $@"
}
greet "Alice" 1 2 3
# 输出:
# Hello, Alice! You have 3 arguments.
# Arguments: Alice 1 2 3
- 函数的返回值
bash 函数的返回值可以通过 return 语句指定,返回值的范围是 0 到 255,其中 0 表示成功,非 0 表示失败。也可以通过输出结果来返回值,使用 $() 捕获函数的输出。例如:
# 使用 return 语句
check_positive() {
if [ $1 -gt 0 ]; then
return 0
else
return 1
fi
}
check_positive 5
echo $? # 输出 0(表示成功)
# 通过输出返回值
multiply() {
echo $(( $1 * $2 ))
}
result=$(multiply 3 4)
echo $result # 输出 12
(五)输入与输出
- 输出命令
- echo:用于输出字符串或变量的值。例如:
echo "Hello, World!"
name="Bob"
echo "Name: $name"
echo 命令支持一些转义字符,如 \n(换行)、\t(制表符)等,需要使用 -e 选项启用转义功能。例如:
echo -e "Line 1\nLine 2"
# 输出:
# Line 1
# Line 2
- printf:用于格式化输出,功能比 echo 更强大,语法与 C 语言中的 printf 函数类似。例如:
printf "Name: %s, Age: %d\n" "Alice" 25
# 输出:Name: Alice, Age: 25
- 输入命令
- read:用于从标准输入读取用户的输入,并将输入赋值给变量。例如:
read name
echo "Hello, $name!"
read 命令可以指定多个变量,输入的内容会按顺序赋值给这些变量,
posted on 2025-08-19 10:41 gamethinker 阅读(19) 评论(0) 收藏 举报 来源
浙公网安备 33010602011771号