张芷铭的个人博客

注释:单行注释以 # 开头(#! 除外)

Bash 脚本是 Linux/Unix 系统中自动化任务的核心工具,语法简洁且实用,以下是最基础、最常用的语法总结,覆盖脚本结构、变量、流程控制、输入输出等核心场景,适合快速上手。

一、脚本基础结构

1. 脚本开头(指定解释器)

必须放在脚本第一行,指定脚本由 Bash 解释执行:

1
2
3
4
5
6
#!/bin/bash
# 注释:单行注释以 # 开头(#! 除外)
: '
多行注释:用 : ' 开头,' 结尾(注意引号成对)
可跨多行,适合大段说明
'

2. 脚本执行方式

  • 先给脚本添加执行权限(仅需一次):
    1
    
    chmod +x script.sh  # script.sh 是你的脚本文件名
    
  • 执行脚本:
    1
    2
    3
    
    ./script.sh  # 相对路径(推荐,执行当前目录下的脚本)
    /home/user/script.sh  # 绝对路径
    bash script.sh  # 直接用 bash 解释器执行(无需执行权限)
    

二、变量与参数

1. 变量定义与使用

  • 定义:变量名=值等号前后无空格,值含空格需用引号包裹);
  • 使用:$变量名${变量名}({} 用于区分变量边界,避免歧义);
  • 示例:
    1
    2
    3
    4
    
    name="Bash"  # 字符串变量(含空格需用引号:name="Hello Bash")
    age=20       # 数值变量(无需引号)
    echo "名称:$name"  # 输出:名称:Bash
    echo "年龄:${age}岁"  # 输出:年龄:20岁({} 明确变量范围)
    

2. 环境变量与内置变量

  • 环境变量:系统预定义,全大写(如 PATHHOMEUSER),可直接使用:
    1
    2
    
    echo "用户主目录:$HOME"  # 输出当前用户主目录(如 /home/ubuntu)
    echo "系统路径:$PATH"    # 输出可执行程序的搜索路径
    
  • 脚本参数变量(接收命令行输入):
变量含义
$0脚本文件名(如 script.sh)
$1~$n第 1~n 个命令行参数
$#命令行参数总个数
$*所有参数(合并为单个字符串)
$@所有参数(保留独立字符串)
$?上一条命令的执行结果(0=成功,非0=失败)
  • 示例:
    1
    2
    3
    4
    5
    
    # 脚本内打印参数
    echo "脚本名:$0"
    echo "第1个参数:$1"
    echo "参数总个数:$#"
    echo "所有参数:$@"
    
    执行 bash script.sh a b c,输出:
    脚本名:script.sh
    第1个参数:a
    参数总个数:3
    所有参数:a b c
    

3. 变量赋值进阶

  • 从命令输出赋值(命令替换):变量名=$(命令)变量名=命令``:
    1
    2
    3
    
    current_dir=$(pwd)  # 获取当前目录,赋值给 current_dir
    file_count=$(ls | wc -l)  # 获取当前目录文件数
    echo "当前目录:$current_dir,文件数:$file_count"
    
  • 只读变量(不可修改):readonly 变量名
    1
    2
    3
    
    pi=3.14159
    readonly pi
    # pi=3.14  # 报错:无法修改只读变量
    

三、输入与输出

1. 输出(echo/printf)

  • echo:简单输出(默认换行):
    1
    2
    
    echo "Hello World"  # 输出字符串(可省略引号)
    echo -n "请输入姓名:"  # -n 不换行(用于接收输入前的提示)
    
  • printf:格式化输出(类似 C 语言,更灵活):
    1
    2
    
    printf "姓名:%s,年龄:%d\n" "Alice" 25  # %s 字符串,%d 整数,\n 换行
    # 输出:姓名:Alice,年龄:25
    

2. 输入(read)

接收用户键盘输入,存入变量:

1
2
3
read -p "请输入姓名:" name  # -p 直接显示提示信息
read -p "请输入年龄:" age
echo "你输入的姓名:$name,年龄:$age"
  • 选项:-t 5 超时时间(5秒未输入则退出),-s 隐藏输入(如输入密码):
    1
    2
    
    read -s -p "请输入密码:" pwd
    echo -e "\n密码已接收"  # -e 解析转义字符(\n 换行)
    

四、流程控制(条件判断+循环)

1. 条件判断(if-else)

语法结构

1
2
3
4
5
6
7
if [ 条件表达式 ]; then  # 注意 [ 后、] 前必须有空格
  执行命令1  # 条件为真时执行
elif [ 条件表达式2 ]; then
  执行命令2  # 条件1为假,条件2为真时执行
else
  执行命令3  # 所有条件为假时执行
fi  # 结束 if 语句(必须闭合)

常用条件表达式

  • 字符串比较:
表达式含义
$a == $b字符串 a 等于 b
$a != $b字符串 a 不等于 b
-z $a字符串 a 为空
-n $a字符串 a 非空
  • 数值比较:
表达式含义
$a -eq $b数值 a 等于 b
$a -ne $b数值 a 不等于 b
$a -gt $b数值 a 大于 b
$a -lt $b数值 a 小于 b
$a -ge $b数值 a 大于等于 b
$a -le $b数值 a 小于等于 b
  • 文件判断:
表达式含义
-f $file文件存在且是普通文件
-d $dir目录存在
-x $script文件可执行
-e $path路径(文件/目录)存在

示例

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
# 数值比较:判断年龄是否成年
age=18
if [ $age -ge 18 ]; then
  echo "已成年"
else
  echo "未成年"
fi

# 文件判断:判断文件是否存在
file="test.txt"
if [ -f $file ]; then
  echo "$file 存在"
else
  echo "$file 不存在,创建文件"
  touch $file  # 创建文件
fi

2. 循环(for/while)

(1)for 循环(遍历列表/范围)

  • 遍历列表:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    
    # 遍历字符串列表
    for name in Alice Bob Charlie; do
      echo "Hello $name"
    done
    
    # 遍历文件列表
    for file in $(ls *.txt); do  # 遍历当前目录下所有 .txt 文件
      echo "文件:$file"
    done
    
  • 遍历数字范围:
    1
    2
    3
    4
    5
    6
    7
    8
    
    # 语法:for 变量 in {起始..结束..步长}(步长可选,默认1)
    for i in {1..5}; do
      echo "循环次数:$i"
    done
    
    for i in {1..10..2}; do  # 步长2(1,3,5,7,9)
      echo "奇数:$i"
    done
    

(2)while 循环(条件为真时执行)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
# 计数器循环(1到5)
i=1
while [ $i -le 5 ]; do
  echo "当前值:$i"
  i=$((i+1))  # 数值计算($((表达式)) 是算术扩展)
done

# 无限循环(需手动退出)
while true; do
  echo "无限循环中(按 Ctrl+C 退出)"
  sleep 1  # 暂停1秒
done

3. 循环控制(break/continue)

  • break:退出当前循环;
  • continue:跳过当前循环剩余部分,进入下一次循环;
  • 示例:
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    
    for i in {1..5}; do
      if [ $i -eq 3 ]; then
        continue  # 跳过 i=3 的循环
      fi
      if [ $i -eq 5 ]; then
        break  # 当 i=5 时退出循环
      fi
      echo "当前值:$i"
    done
    # 输出:1 2 4
    

五、函数

1. 函数定义与调用

1
2
3
4
5
6
7
8
# 定义函数(两种写法,效果一致)
function hello() {  # function 关键字可省略
  echo "Hello $1"  # $1 是函数的第一个参数(函数内参数用法和脚本一致)
}

# 调用函数
hello "Bash"  # 传递参数,输出:Hello Bash
hello "World"  # 输出:Hello World

2. 函数返回值

Bash 函数无“返回值”概念,可通过以下方式返回结果:

  • 直接输出(脚本中用 $(函数名) 捕获);
  • return 返回状态码(0=成功,非0=失败,仅能返回整数);
  • 示例:
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    
    # 函数返回两数之和(通过输出捕获)
    add() {
      sum=$(( $1 + $2 ))
      echo $sum  # 输出结果
    }
    
    # 调用函数并捕获结果
    result=$(add 3 5)
    echo "3+5=$result"  # 输出:3+5=8
    
    # 用 return 返回状态码
    check_num() {
      if [ $1 -gt 10 ]; then
        return 0  # 成功(状态码0)
      else
        return 1  # 失败(状态码1)
      fi
    }
    
    check_num 15
    echo $?  # 输出 0(成功)
    

六、文件操作

1. 基础文件命令(脚本中常用)

命令功能示例
touch 文件名创建空文件touch test.txt
mkdir 目录名创建目录(-p 递归创建)mkdir -p ./data/logs
cp 源 目标复制文件/目录(-r 递归)cp test.txt ./data/
mv 源 目标移动/重命名文件mv test.txt test_new.txt
rm 文件名删除文件(-f 强制,-r 递归删目录)rm -rf ./tmp/(谨慎使用!)
cat 文件名读取文件内容cat test.txt
grep 关键词 文件名搜索文件内容grep "error" log.txt

2. 文件内容重定向

  • >:覆盖写入文件(原有内容清空);
  • >>:追加写入文件(原有内容保留);
  • <:从文件读取输入;
  • 示例:
    1
    2
    3
    4
    5
    6
    
    echo "Hello" > test.txt  # 覆盖写入 test.txt
    echo "World" >> test.txt  # 追加写入 test.txt
    cat test.txt  # 输出:Hello\nWorld
    
    # 把命令输出写入文件
    ls -l > file_list.txt  # 把目录列表写入 file_list.txt
    

七、常用技巧与避坑指南

  1. 空格问题
    • 变量定义:name="Bash"(等号前后无空格);
    • 条件判断:[ $a -eq $b ]([ 后、] 前必须有空格);
  2. 字符串含空格:变量赋值和使用时用引号包裹(name="Hello Bash"echo "$name");
  3. 数值计算:用 $((表达式))$[表达式],避免直接用 + 拼接(如 $((a+b)) 而非 $a+$b);
  4. 脚本调试:执行时加 -x 参数,打印每一步执行的命令:bash -x script.sh
  5. 权限问题:脚本执行前需加执行权限(chmod +x script.sh),或直接用 bash script.sh 执行;
  6. 路径问题:脚本中尽量用绝对路径(如 /home/user/data),避免相对路径导致的错误。

总结

Bash 脚本核心是“自动化命令组合”,基础语法围绕「变量-流程控制-文件操作」展开:

  • 简单任务用「变量+基础命令+重定向」;
  • 复杂逻辑用「条件判断+循环+函数」;
  • 接收输入用「位置参数/read」,输出结果用「echo/printf/文件重定向」。

多写多练(如自动化部署、日志分析、数据处理脚本)是掌握的关键,遇到问题可通过 bash -x 调试,或查看命令返回状态码($?)定位问题。

💬 评论