Bash基础语法入门指南
1. Bash 简介
Bash(Bourne Again SHell)是 Linux 和 macOS 系统中最常用的 shell 程序,它是 Bourne Shell 的一个增强版本。Shell 是用户与操作系统内核之间的接口,通过命令行输入,Bash 解释并执行用户的指令,实现对系统的各种操作。
2. 变量
2.1 变量定义
在 Bash 中定义变量非常简单,语法为:变量名=变量值
。例如:
name="John"
注意,等号两边不能有空格。变量名一般遵循以下规则:
- 由字母、数字和下划线组成。
- 不能以数字开头。
2.2 变量引用
引用变量时,在变量名前加上 $
符号,例如:
name="John"
echo $name
上面的代码会输出 John
。如果要在字符串中引用变量,可以使用双引号,例如:
name="John"
echo "Hello, $name"
这会输出 Hello, John
。如果使用单引号,变量不会被替换,例如:
name="John"
echo 'Hello, $name'
输出为 Hello, $name
。
2.3 环境变量
环境变量是具有特殊意义的变量,会影响 shell 以及运行在其中的程序的行为。常见的环境变量有 PATH
、HOME
等。可以使用 export
命令将普通变量提升为环境变量,例如:
myvar="test"
export myvar
也可以在定义变量时直接声明为环境变量:
export myenvvar="envtest"
可以通过 echo $环境变量名
查看环境变量的值,例如 echo $PATH
会显示系统的可执行文件搜索路径。
2.4 只读变量
使用 readonly
命令可以将变量设置为只读,一旦设置为只读,就不能再修改其值。例如:
readonly myreadonlyvar="readonlytest"
myreadonlyvar="newvalue" # 这会报错
运行上述代码,会提示 bash: myreadonlyvar: readonly variable
。
3. 数据类型
3.1 字符串
Bash 中的字符串无需特别声明类型,直接定义即可。字符串可以用单引号或双引号括起来。单引号内的所有字符都按字面意思处理,双引号内的变量会被替换,并且支持转义字符。例如:
single_str='This is a single - quoted string with $name'
double_str="This is a double - quoted string with $name"
echo $single_str
echo $double_str
输出结果:
This is a single - quoted string with $name
This is a double - quoted string with John
3.2 数组
Bash 支持一维数组,定义数组的方式有多种。例如:
# 方式一
my_array=(element1 element2 element3)
# 方式二
my_array[0]=element1
my_array[1]=element2
my_array[2]=element3
访问数组元素使用 ${数组名[索引]}
,例如:
echo ${my_array[0]}
这会输出 element1
。获取数组所有元素使用 ${数组名[@]}
或 ${数组名[*]}
,例如:
echo ${my_array[@]}
会输出 element1 element2 element3
。获取数组长度使用 ${#数组名[@]}
,例如:
echo ${#my_array[@]}
输出 3
,即数组的元素个数。
4. 运算符
4.1 算术运算符
Bash 支持基本的算术运算,如加、减、乘、除等。但是需要使用特定的语法。例如,使用 $((运算表达式))
或 let "变量=运算表达式"
。
a=5
b=3
# 使用 $((运算表达式))
result1=$((a + b))
echo $result1
# 使用 let
let "result2=a - b"
echo $result2
上述代码分别输出 8
和 2
。支持的运算符有 +
(加)、-
(减)、*
(乘)、/
(除)、%
(取余)、**
(幂运算)等。
4.2 比较运算符
比较运算符用于比较两个数的大小等关系。常用的有 -eq
(等于)、-ne
(不等于)、-gt
(大于)、-lt
(小于)、-ge
(大于等于)、-le
(小于等于)。这些运算符一般用于条件判断语句中。例如:
a=5
b=3
if [ $a -gt $b ]; then
echo "$a 大于 $b"
fi
上述代码会输出 5 大于 3
。
4.3 逻辑运算符
逻辑运算符有 &&
(逻辑与)、||
(逻辑或)、!
(逻辑非)。例如:
a=5
b=3
if [ $a -gt $b ] && [ $a -lt 10 ]; then
echo "$a 大于 $b 且小于 10"
fi
上述代码会输出 5 大于 3 且小于 10
。
4.4 字符串运算符
字符串运算符用于对字符串进行比较等操作。例如 =
(字符串相等)、!=
(字符串不相等)、-z
(字符串长度为 0)、-n
(字符串长度不为 0)。例如:
str1="hello"
str2="world"
if [ $str1 != $str2 ]; then
echo "字符串不相等"
fi
上述代码会输出 字符串不相等
。
5. 条件判断
5.1 if 语句
if 语句是最基本的条件判断语句,语法如下:
if [ 条件判断 ]; then
命令1
命令2
...
elif [ 条件判断2 ]; then
命令3
命令4
...
else
命令5
命令6
...
fi
例如:
num=10
if [ $num -gt 15 ]; then
echo "数字大于 15"
elif [ $num -gt 5 ]; then
echo "数字大于 5 小于等于 15"
else
echo "数字小于等于 5"
fi
上述代码会输出 数字大于 5 小于等于 15
。
5.2 case 语句
case 语句用于多分支选择,语法如下:
case 变量 in
模式1)
命令1
命令2
;;
模式2)
命令3
命令4
;;
*)
命令5
命令6
;;
esac
例如:
fruit="apple"
case $fruit in
apple)
echo "这是苹果"
;;
banana)
echo "这是香蕉"
;;
*)
echo "不知道这是什么水果"
;;
esac
上述代码会输出 这是苹果
。
6. 循环
6.1 for 循环
for 循环用于按指定次数执行一组命令。语法有两种常见形式。 形式一:
for 变量 in 列表; do
命令1
命令2
...
done
例如:
for num in 1 2 3 4 5; do
echo $num
done
上述代码会依次输出 1
2
3
4
5
。
形式二:
for (( 初始值; 条件判断; 增量 )); do
命令1
命令2
...
done
例如:
for ((i = 1; i <= 5; i++)); do
echo $i
done
同样会依次输出 1
到 5
。
6.2 while 循环
while 循环只要条件为真就会一直执行。语法如下:
while [ 条件判断 ]; do
命令1
命令2
...
done
例如:
num=1
while [ $num -le 5 ]; do
echo $num
num=$((num + 1))
done
上述代码会输出 1
到 5
。
6.3 until 循环
until 循环与 while 循环相反,只要条件为假就会一直执行,直到条件为真停止。语法如下:
until [ 条件判断 ]; do
命令1
命令2
...
done
例如:
num=1
until [ $num -gt 5 ]; do
echo $num
num=$((num + 1))
done
同样会输出 1
到 5
。
7. 函数
7.1 函数定义
在 Bash 中定义函数的语法如下:
函数名() {
命令1
命令2
...
[return 返回值]
}
例如:
print_hello() {
echo "Hello, World!"
}
7.2 函数调用
定义好函数后,可以直接通过函数名调用,例如:
print_hello
上述代码会输出 Hello, World!
。
7.3 函数参数
函数可以接受参数,在函数内部通过 $1
、$2
等变量来访问参数,$0
表示脚本本身的名字(如果在脚本中定义函数)。例如:
add_numbers() {
result=$(( $1 + $2 ))
echo "两数之和为: $result"
}
add_numbers 3 5
上述代码会输出 两数之和为: 8
。
7.4 函数返回值
可以使用 return
语句返回一个值,返回值范围是 0 到 255。例如:
square() {
result=$(( $1 * $1 ))
return $result
}
square 5
return_value=$?
echo "返回值为: $return_value"
上述代码会输出 返回值为: 25
,$?
用于获取上一个命令(这里是函数)的返回值。
8. 文件操作
8.1 文件创建
使用 touch
命令可以创建一个空文件,例如:
touch newfile.txt
8.2 文件读取
可以使用 cat
命令读取文件内容并输出到终端,例如:
cat newfile.txt
如果文件较大,可以使用 less
命令,它支持分页查看,例如:
less newfile.txt
按 q
键可以退出 less
查看。
8.3 文件写入
使用 echo
配合重定向符号 >
或 >>
可以写入文件。>
会覆盖原有内容,>>
会追加内容。例如:
echo "这是写入的内容" > newfile.txt
echo "这是追加的内容" >> newfile.txt
8.4 文件删除
使用 rm
命令可以删除文件,例如:
rm newfile.txt
如果要删除目录及目录下所有文件,使用 rm -r
,例如:
rm -r mydirectory
注意,使用 rm
命令要谨慎,因为删除后数据难以恢复。
8.5 文件权限操作
使用 chmod
命令可以改变文件或目录的权限。权限分为读(r
)、写(w
)、执行(x
)。例如,给文件 testfile
添加可执行权限:
chmod +x testfile
可以使用数字表示权限,例如 755
表示所有者有读、写、执行权限,组用户和其他用户有读和执行权限。设置文件权限为 755
:
chmod 755 testfile
9. 脚本执行
9.1 直接执行
将一系列 Bash 命令保存到一个文件中,例如 myscript.sh
,然后给文件添加可执行权限:
chmod +x myscript.sh
之后可以直接执行脚本:
./myscript.sh
9.2 使用 bash 命令执行
也可以不添加可执行权限,直接使用 bash
命令执行脚本,例如:
bash myscript.sh
在脚本开头添加 #!/bin/bash
称为 shebang,它指定了执行该脚本的程序,这样在添加可执行权限后就可以直接执行脚本,而不需要在命令前加上 bash
。例如:
#!/bin/bash
echo "这是一个脚本"
保存为 myscript.sh
,添加可执行权限后,直接执行 ./myscript.sh
即可。
10. 命令替换
10.1 反引号方式
可以使用反引号(`)将命令括起来,Bash 会执行反引号中的命令,并将输出结果替换到原位置。例如:
current_date=`date`
echo "当前日期是: $current_date"
上述代码会输出当前日期,例如 当前日期是: Fri Aug 11 15:30:00 CST 2023
。
10.2 $( ) 方式
更推荐使用 $( )
方式进行命令替换,例如:
current_dir=$(pwd)
echo "当前目录是: $current_dir"
这会输出当前所在目录路径。
11. 输入输出重定向
11.1 输出重定向
前面提到过使用 >
覆盖输出和 >>
追加输出到文件。例如:
ls > filelist.txt # 将 ls 命令的输出覆盖写入 filelist.txt
echo "追加内容" >> filelist.txt # 追加内容到 filelist.txt
11.2 输入重定向
使用 <
可以进行输入重定向,将文件内容作为命令的输入。例如,假设有一个 input.txt
文件内容为 Hello
,可以这样使用:
read line < input.txt
echo "读取的内容是: $line"
上述代码会输出 读取的内容是: Hello
。
11.3 错误输出重定向
使用 2>
可以将错误输出重定向到文件。例如,执行一个不存在的命令:
nonexistentcommand 2> error.log
命令执行产生的错误信息会被写入 error.log
文件。也可以同时重定向标准输出和错误输出,例如:
command 2>&1 > output.log
这样标准输出和错误输出都会被写入 output.log
文件。
12. 管道
管道(|
)可以将一个命令的输出作为另一个命令的输入。例如,要查看当前目录下文件数量,可以这样:
ls | wc -l
ls
命令列出目录下的文件,wc -l
统计行数,这里就是文件数量。再比如,要在当前目录及子目录中查找包含特定字符串的文件,可以使用:
grep -r "特定字符串" . | less
grep -r "特定字符串" .
会递归查找当前目录(.
)下包含特定字符串的文件及行,| less
将结果通过 less
分页显示。
13. 信号处理
13.1 捕获信号
在脚本中可以使用 trap
命令捕获信号并执行相应的处理程序。例如,捕获 SIGINT
(通常是 Ctrl+C
)信号,在用户按下 Ctrl+C
时输出一条提示信息:
#!/bin/bash
trap 'echo "你按下了 Ctrl+C,程序即将退出。"' SIGINT
while true; do
echo "程序正在运行..."
sleep 1
done
上述脚本在运行时,当用户按下 Ctrl+C
,会输出提示信息后退出。
13.2 发送信号
使用 kill
命令可以向进程发送信号。例如,要终止一个进程,首先通过 ps
命令找到进程 ID,假设进程 ID 为 1234
,可以这样发送终止信号:
kill 1234
如果要发送其他信号,可以使用 -信号编号
或 -信号名
的方式,例如发送 SIGTERM
信号:
kill -SIGTERM 1234
14. 调试
14.1 调试选项
在脚本开头添加 set -x
可以开启调试模式,Bash 会在执行每一条命令前打印命令及其参数。例如:
#!/bin/bash
set -x
a=5
b=3
result=$((a + b))
echo "结果是: $result"
运行脚本时,会看到类似如下输出:
+ a=5
+ b=3
+ result=8
+ echo '结果是: 8'
结果是: 8
+
开头的行就是调试信息,显示了实际执行的命令。调试完成后,可以使用 set +x
关闭调试模式。
14.2 错误处理
使用 set -e
可以使脚本在遇到错误(命令返回非零状态码)时立即停止执行。例如:
#!/bin/bash
set -e
nonexistentcommand # 这会导致错误
echo "这行不会被执行"
上述脚本运行到 nonexistentcommand
时会报错并停止执行,不会输出 这行不会被执行
。
通过掌握以上这些 Bash 基础语法,你可以编写各种自动化脚本,提高在 Linux 或 macOS 系统下的工作效率,无论是系统管理、文件处理还是其他各种任务,Bash 脚本都能发挥巨大的作用。在实际应用中,不断练习和尝试,结合具体需求编写合适的脚本,进一步提升自己在命令行环境下的操作能力。