INTERACTIVE LAB

systems0 次浏览 更新于 2026-09-30

Bash 变量、数组与展开

集中讲清 Bash 的变量、数组、引号、展开和 Here 文档。

下一课「Bash 函数」起需 VIP,当前篇是免费路径的最后一课。

变量

Bash 变量没有单独的数据类型,通常都按字符串处理。赋值时等号两边不能有空格:

name="hello world"
count=3
echo "$name: $count"

变量名只能包含字母、数字和下划线,且不能以数字开头。环境变量通常用大写命名,例如 HOME、PATH、USER。env 或 printenv 可以查看环境变量,set 还会列出当前 Shell 的自定义变量和函数。

自定义变量只属于当前 Shell。需要让子 Shell 继承时,用 export:

export APP_ENV=dev
bash -c 'echo "$APP_ENV"'

unset NAME 可以删除变量;变量不存在时展开结果通常是空字符串。需要区分“未设置”和“空值”时,可以使用参数展开:

echo "${name:-匿名}"       # 没有值时使用匿名
name="${name:-匿名}"       # 没有值时顺便赋值
file="${1:?缺少文件名}"    # 没有值时打印错误并退出

常见特殊变量包括 $?(上一条命令的退出码)、$$(当前 Shell 的 PID)、$!(最近一个后台任务的 PID)、$0(脚本名)以及脚本参数 $#、$@。

引用与展开

双引号会保留空格,并仍然允许变量、命令和算术展开;单引号几乎完全按字面保留内容:

value="a  b"
echo $value       # 空格可能被重新分词
echo "$value"     # 保留连续空格
echo '$value'     # 输出字面量 $value

反斜杠可以转义特殊字符。命令替换推荐使用 $(...),算术展开使用 $((...)):

today="$(date +%F)"
total=$((2 + 3))
echo "$today $total"

文件名展开(glob)由 Bash 在执行命令前完成:*.log 匹配当前目录的日志文件,? 匹配一个字符,[ab] 匹配 a 或 b。它不是正则表达式,也不会自动递归子目录;文件名可能包含空格时,遍历要写成 for file in ./*.log; do ... "$file"; done。

字符串也可以用参数展开处理:

path="/tmp/archive.tar.gz"
echo "${path##*/}"  # archive.tar.gz
echo "${path%.*}"   # /tmp/archive.tar
echo "${path//tmp/data}"
echo "${#path}"

数组

普通数组从下标 0 开始:

names=("小明" "小红")
names+=( "小刚" )

echo "${names[0]}"
echo "成员数:${#names[@]}"

for name in "${names[@]}"; do
  echo "$name"
done

"${array[@]}" 会把每个成员作为独立参数,通常是遍历数组的正确写法;"${array[*]}" 在双引号中会把所有成员合成一个字符串。

可以删除成员或追加成员:

unset 'names[1]'
names+=( "新成员" )

关联数组需要先声明:

declare -A colors
colors[red]="#f00"
colors[blue]="#00f"
echo "${colors[red]}"

Here 文档与 Here 字符串

Here 文档适合给命令提供多行标准输入,结束标记必须单独占一行:

cat <<'EOF'
第一行
第二行
EOF

标记不加引号时,会进行变量和命令替换;加单引号则按字面处理:

name="Bash"
cat <<EOF
你好,$name
EOF

cat <<'EOF'
$name 不会被替换
EOF

Here 字符串 <<< 适合传入一行内容:

grep "bash" <<< "$line"

这里的重点是输入重定向,不要把 Here 文档误当成给变量赋多行值的特殊语法。

DISCUSSION

评论 0

还没有评论,来留下第一条吧。