Shell脚本编程——变量用法详解
一、变量基础概念
1.1 什么是变量?
变量是命名的内存空间,用于存储数据(如字符串、数字等)。通过变量名可以快速引用和操作这些数据,避免重复输入复杂内容。
1.2 变量的作用
- •
简化操作:用有意义的名称代替重复的数据(如
PATH=/usr/bin:/usr/local/bin
)。 - •
灵活控制:通过修改变量值动态调整脚本行为(如根据用户输入切换路径)。
- •
提高可读性:清晰的变量名让代码更易理解(如
USER_NAME=admin
比直接写admin
更直观)。
二、变量类型
Shell中的变量按用途和特性分为以下几类:
类型 | 说明 | 示例 |
---|---|---|
内置变量 | Shell预定义的系统变量(只读或全局生效),如 |
|
用户自定义变量 | 用户手动定义的变量,用于存储脚本中需要的数据 |
|
预定义变量 | Shell内置的特殊变量(如 |
|
位置变量 | 用于接收脚本运行时传递的参数(如 | 执行 |
2.1 变量数据类型
- •
字符串:文本数据(如
"Hello"
、'World'
),Shell默认所有变量均为字符串。 - •
数值:
- •
整型:整数(如
10
、-5
),Bash可直接处理。 - •
浮点型(小数):Bash不支持(如
3.14
需借助外部工具如bc
计算)。
- •
三、变量命名规则
3.1 合法命名要求
- •
字符限制:只能包含 数字、字母、下划线(如
user_name
、AGE_20
)。 - •
禁止数字开头:不能以数字开头(如
1name
❌,name1
✅)。 - •
避开保留字:不能使用Shell关键字(如
if
、for
、while
)。 - •
推荐命名风格:
- •
见名思义:变量名体现用途(如
username
比a
更清晰)。 - •
统一规范:
- •
全大写:环境变量或全局常量(如
PATH
、MAX_SIZE
)。 - •
小写:局部变量和函数名(如
count
、calculate_sum
)。
- •
- •
四、变量的定义与使用
4.1 定义变量
格式:变量名="值"
(等号两侧不能有空格!)
常见赋值方式:
name='Mike' # 直接字符串(单引号包裹,内容原样输出)
NAME="$USER" # 引用其他变量(双引号内变量会被解析)
hostname=`hostname` # 命令结果(反引号,旧写法)
hostname=$(hostname) # 命令结果(推荐,更清晰的 $( ) 写法)
FILE=/etc/* # 通配符(匹配 /etc 下所有文件)
⚠️ 注意:变量赋值仅在当前Shell进程中有效,关闭终端后自动失效(除非写入配置文件如
~/.bashrc
)。
4.2 引用变量
- •
基本引用:
$变量名
(如echo $name
)或${变量名}
(推荐,避免歧义)。 - •
弱引用 vs 强引用:
- •
弱引用
$var
:变量会被替换为实际值(如echo "Name: $name"
→ 输出Name: Mike
)。 - •
**强引用 'var′‘∗∗:变量保持原字符串(如‘echo′Name:name'
→ 输出
Name: $name`)。
- •
4.3 特殊场景:变量名相邻时的处理
若变量名与其他字符相连(如 ${NAME}_AGE
),必须用 ${ }
明确边界,否则Shell会误解析:
NAME=mage
echo $NAME_AGE # 错误!Shell尝试找变量 NAME_AGE(不存在,默认为空)
echo ${NAME}_AGE # 正确!输出 "mage_AGE"
五、变量作用域
变量的生效范围(作用域)决定了它能在哪些Shell进程中使用:
类型 | 生效范围 | 示例场景 |
---|---|---|
普通变量 | 当前Shell进程 | 在终端直接定义的变量(如 |
环境变量 | 当前Shell及其所有子进程 | 通过 |
本地变量 | 当前Shell的某个代码片段(如函数内部) | 函数内定义的变量(默认仅函数内可用,除非用 |
📌 环境变量通常用于配置全局信息(如
PATH
),普通变量多用于脚本内部临时存储。
六、常用变量操作命令
6.1 查看所有变量
- •
set
:显示所有变量(包括用户自定义、环境变量、函数等)。 - •
env
或printenv
:仅显示环境变量。 - •
export
:显示已导出的环境变量。 - •
declare -x
:同export
,显示环境变量。
6.2 删除变量
unset 变量名1 变量名2 # 删除指定变量(如 unset name age)
删除后,该变量不可再被引用(echo $变量名
输出空)。
七、特殊变量详解
7.1 环境变量
- •
作用:子进程(包括孙子进程)可继承父进程的环境变量,但子进程的修改不会影响父进程。
- •
定义方法:
export 变量名=value # 推荐写法(先赋值再导出) 变量名=value; export 变量名 # 分步写法 declare -x 变量名=value # 使用 declare 命令
- •
示例:让子脚本使用父脚本定义的变量
# father.sh #!/bin/bash NAME="father" export NAME # 导出为环境变量 echo "Father: $NAME" ./son.sh # 调用子脚本# son.sh #!/bin/bash echo "Son: $NAME" # 子脚本可访问父脚本导出的 NAME NAME="son" # 子脚本修改自己的 NAME(不影响父脚本) echo "Son修改后: $NAME"
7.2 只读变量
- •
特点:定义后不可修改、不可删除,用于存储固定值(如配置常量)。
- •
定义方法:
readonly 变量名=value declare -r 变量名=value
- •
示例:
readonly PI=3.14 PI=3.14159 # 报错:PI: 只读变量 unset PI # 报错:无法删除只读变量
7.3 位置变量
用于接收脚本运行时传递的参数(通过命令行传入):
变量 | 说明 | 示例(执行 |
---|---|---|
| 脚本名称(含路径) |
|
| 第1个参数 |
|
| 第2个参数 |
|
... | ... | ... |
| 第9个参数 | (超过9需用 |
| 参数的总个数 |
|
| 所有参数合并为单个字符串 |
|
| 所有参数为独立字符串 |
|
| 上一条命令的退出状态码 |
|
| 当前Shell进程的PID | 脚本自身的进程ID |
📌 注意:
$*
和$@
在双引号中表现不同:
- •
"$*"
:所有参数合并为一个字符串(如"A B C"
)。- •
"$@"
:每个参数作为独立字符串(如"A" "B" "C"
),推荐在循环中遍历参数时使用。
7.4 退出状态码变量 $?
- •
作用:存储上一条命令或函数的执行结果(0表示成功,非0表示失败)。
- •
常见状态码:
- •
0
:成功。 - •
1
:一般错误(如参数错误)。 - •
127
:命令未找到(如输入了错误的命令名)。
- •
- •
自定义退出:通过
exit n
主动设置脚本退出状态(如exit 0
表示成功)。
八、变量操作进阶
8.1 命令替换
通过命令执行结果赋值给变量:
# 反引号(旧写法)
current_date=`date +%Y-%m-%d`# 推荐写法($( ))
current_dir=$(pwd)
files_count=$(ls | wc -l)
8.2 数值计算(整型)
Bash默认不支持浮点数,但可通过 $(( ))
或 let
进行整数运算:
a=10
b=20
sum=$((a + b)) # sum=30
let "product=a*b" # product=200
8.3 展开命令行规则
Shell处理命令行时按以下顺序:
- 1.
拆分命令词 → 2. 展开别名 → 3. 处理
{}
大括号 → 4. 处理~
家目录 → 5. 命令替换$( )
或` `
→ 6. 再次拆分词 → 7. 处理通配符*
/?
→ 8. 准备输入/输出重定向<
/>
→ 9. 执行命令。
8.4 防止扩展(避免特殊字符被解析)
- •
**反斜线
\`**:转义单个字符(如
echo Your cost: $5.00→ 输出
Your cost: $5.00`)。 - •
引号:
- •
单引号
' '
:禁止所有扩展(如echo '$PATH'
→ 输出$PATH
)。 - •
双引号
" "
:允许部分扩展(如变量$VAR
会被解析,但命令替换` `
或$( )
仍生效)。
- •
九、实战示例
示例1:显示系统信息脚本(OS.sh)
#!/bin/bash
RED="\E[1;31m"
GREEN="\E[1;32m"
END="\E[0m"
echo -e "${GREEN}----------Host systeminfo----------${END}"
echo -e "HOSTNAME: ${RED}$(hostname)${END}"
echo -e "IPADDR: ${RED}$(ifconfig ens160 | grep -Eo '([0-9]{1,3}\.){3}[0-9]{1,3}' | head -n1)${END}"
echo -e "OSVERSION: ${RED}$(cat /etc/redhat-release)${END}"
echo -e "KERNEL: ${RED}$(uname -r)${END}"
echo -e "CPU: ${RED}$(lscpu | grep "型号名称:" | tr -s ' ' ' '|cut -d ' ' -f 2-5)${END}"
echo -e "MEMORY: ${RED}$(free -h | grep Mem | tr -s ' ' ' '|cut -d ' ' -f 4)${END}"
echo -e "DISK: ${RED}$(lsblk | grep '^sda' | tr -s ' ' | cut -d ' ' -f 4)${END}"
echo -e "${GREEN}---------- END ----------${END}"
运行:chmod +x OS.sh && ./OS.sh
示例2:通过变量动态执行命令
CMD=hostname
$CMD # 实际执行 hostname 命令,输出当前主机名
十、总结
- •
变量是Shell脚本的核心:合理使用变量能让脚本更灵活、可维护。
- •
命名规范是关键:遵循规则(如避免数字开头、用有意义的名字)减少错误。
- •
作用域决定使用场景:普通变量用于脚本内部,环境变量用于跨进程传递信息。
- •
特殊变量(如
$1
、$?
)是脚本交互的基础:掌握它们才能编写实用的参数处理和错误判断逻辑。