在 Linux 系统的 Shell 环境中,变量是存储临时数据、配置选项和脚本参数的基本单位。理解变量的定义、引用和作用域,是编写可靠 Shell 脚本的第一步。
1. 自定义变量
在 Bash 中,自定义变量的语法非常简单:等号两边不能有空格。
name="Linux" # 定义一个字符串变量
count=10 # 定义一个整型(实际上仍是字符串)
pi=3.14 # 定义浮点数(同样作为字符串处理)
readonly constant=100 # 定义一个只读常量
变量名通常使用大写(习惯约定),但小写也合法。如果需要包含空格或特殊字符,需要用引号包围:
greeting="Hello, World!"
file_path="/home/user/my documents/report.txt" # 包含空格需用双引号
常用内置变量可以当做系统预设的自定义变量来使用,例如 $HOME、$USER、$PATH 等。你也可以修改它们(不建议随意修改系统变量):
PATH="$PATH:/opt/myapp/bin" # 将自定义目录追加到 PATH 中
2. 变量引用
要获取变量的值,需要在变量名前加上 $ 符号,或者使用 ${} 进行明确界定:
echo $name # 输出 Linux
echo "Hello, ${name}" # 输出 Hello, Linux
echo "${name} is great" # 明确变量名边界,避免歧义
${} 形式在变量名与后续字符可能混淆时尤其重要:
filename="report"
touch "${filename}_2025.txt" # 创建 report_2025.txt
# 如果写成 touch "$filename_2025.txt" 会去查找名为 filename_2025 的变量
除了直接引用,Bash 还提供一些常用的变量展开技巧:
- 默认值:
${var:-默认值}如果 var 未定义或为空,使用默认值。
echo "Your name: ${username:-Guest}" # 若未设置 username,则输出 Guest
- 指定默认值并赋给变量:
${var:=默认值}
: ${count:=0} # 若 count 未设置,则赋值为 0
- 错误提示:
${var:?错误信息},若 var 未定义则退出并打印错误信息。
- 替换:
${var/pattern/replacement}替换匹配的内容(仅一次),${var//pattern/replacement}全局替换。
引用命令的输出要用命令替换 $(...),它实际上是将命令的输出赋给变量:
today=$(date +%F)
echo "Today is $today"
3. 变量作用域
在 Bash 中,变量的作用域默认是全局的:在一个 Shell 会话中定义的变量,会对当前 Shell 以及从这个 Shell 启动的所有子进程可见(前提是使用 export 导出)。
- 默认变量不会是环境变量:直接在脚本中定义的变量,不会传递给子进程(如脚本中调用的其他命令或脚本)。要让子进程继承,必须用
export将其标记为环境变量,或直接在赋值时使用export:
myvar="hello" # 只在当前 Shell 可见
export myvar # 现在子进程也能访问
export var2="world" # 定义并导出一步完成
- 函数中的局部变量:在 Shell 函数内部,使用
local关键字定义局部变量,其作用范围仅限于函数内部,不会覆盖外部的同名变量,也不会在函数返回后保留。
#!/bin/bash
global_var="I am global"
myfunc() {
local global_var="I am local" # 遮蔽了外部同名变量
echo "Inside function: $global_var"
}
myfunc
echo "Outside function: $global_var" # 仍然输出 I am global
如果没有 local,函数内的赋值就会直接修改外部的全局变量,这往往是脚本产生 Bug 的常见来源。
- 通过括号
()创建子 Shell 隔离作用域:
a=100
( a=200; echo "in subshell: $a" ) # 输出 200
echo "in parent: $a" # 输出 100,子 Shell 的修改不影响父 Shell
掌握变量的作用域控制,能够避免脚本中的意外副作用,特别是在编写复杂、会调用其他函数和脚本的自动化任务时至关重要。