以下是关于 Shell 变量 的详细讲解,涵盖定义、类型、使用方法及常见操作:
1. Shell 变量的定义与命名规则
定义方式
-
使用
=
连接变量名和值,等号两侧不能有空格。 -
如果值包含空格或特殊字符,需要用引号(单引号或双引号)包裹。
- 单引号里的任何字符都会原样输出,单引号字符串中的变量是无效的
- 双引号里可以有变量、可以有转义字符
# 正确示例 my_var=Hello World' path="/usr/local/bin" my_path="/path with space" # 错误示例 my var="Hello World" # 等号两侧不能有空格
命名规则
-
字符限制:只能由字母(a-z, A-Z)、数字(0-9)和下划线(_)组成。
-
首字符限制:必须以字母或下划线开头,不能以数字开头。
-
大小写敏感:
VAR
和var
是两个不同的变量。 -
描述性:建议使用有意义的名称(如
count
表示计数,file_path
表示文件路径)。1Invalid="Valid"
2. 变量的引用
基本引用
-
使用
$变量名
或${变量名}
引用变量值:name="Alice" echo "Hello, $name" # 输出: Hello, Alice echo "Hello, ${name}!" # 输出: Hello, Alice!
复杂场景
-
避免歧义:当变量名后紧跟其他字符时,用
${}
明确边界:count=5 echo "Count is $count6" # 输出: Count is 6 (可能被解析为 $count6) echo "Count is ${count}6" # 输出: Count is 56
3. 特殊变量
Shell 提供了一些预定义变量,用于脚本参数传递和状态管理:
变量 | 作用 |
---|---|
$0 | 脚本名称(包括路径) |
$n | 第 n 个参数(n 为 1~9,超过 9 用 ${10} 等) |
$# | 传递给脚本的参数总个数 |
$* | 所有参数作为一个字符串("$*" 会合并为单个字符串) |
$@ | 所有参数作为独立字符串("$@" 保留每个参数的独立性) |
$? | 上一条命令的退出状态码(0 表示成功,非 0 表示失败) |
$$ | 当前 Shell 脚本的进程 PID |
$! | 上一个后台进程的 PID |
$_ | 上一条命令的最后一个参数 |
示例:
#!/bin/bash
echo "脚本名称: $0"
echo "第一个参数: $1"
echo "参数总数: $#"
echo "所有参数: $@"
运行命令:
./script.sh arg1 arg2
输出:
脚本名称: ./script.sh
第一个参数: arg1
参数总数: 2
所有参数: arg1 arg2
4. 环境变量 vs 本地变量
本地变量
-
仅在当前 Shell 会话中有效,退出后失效。
-
定义:
var="value"
-
示例:
name="Alice" echo $name # 输出: Alice exit echo $name # 输出为空(退出后变量失效)
环境变量
-
对当前 Shell 及其子进程可见。
-
定义:
export var="value"
-
示例:
export PATH="$PATH:/custom/path"
5. 变量操作
字符串操作
-
字符串替换:
-
Shell 提供了内置的变量替换语法
无需调用外部命令,性能较高
${variable/pattern/replacement}
替换第一个匹配项
str="hello world" echo ${str/hello/hi} # 输出: hi world
替换所有匹配项
str="apple banana apple" echo ${str//apple/orange} # 输出: orange banana orange
替换特殊字符(如 /)
path="c:/windows/boot.ini" echo ${path//\//\\} # 输出: c:\windows\boot.ini
-
sed
命令:是一个流编辑器,适合处理文件或字符串的复杂替换操作
sed 's/pattern/replacement/' input
替换第一个匹配项
echo "hello world" | sed 's/hello/hi/' # 输出: hi world
全局替换(所有匹配项)
echo "apple banana apple" | sed 's/apple/orange/g' # 输出: orange banana orange
替换文件内容
sed -i 's/old/new/g' filename.txt # 直接修改文件内容
正则表达式替换
echo "2025-06-21" | sed 's/-/./g' # 输出: 2025.06.21
-
awk
命令:是一种文本处理工具,适合按字段处理字符串替换
awk '{gsub(/pattern/, "replacement"); print}' input
全局替换
echo "apple banana apple" | awk '{gsub(/apple/, "orange"); print}' # 输出: orange banana orange
按字段替换
echo "www.baidu.com" | awk -F. '{ $1 = "new"; OFS="."; print }' # 输出: new.baidu.com
-
perl
命令:提供了强大的正则表达式替换功能,适合复杂场景
perl -pe 's/pattern/replacement/' input
示例
echo "2025-06-21" | perl -pe 's/-/./g' # 输出: 2025.06.21
-
tr
:用于字符级别的替换、删除或压缩,适合处理单字符替换
tr 'SET1' 'SET2' < input
字符替换
echo "hello" | tr 'aeiou' 'AEIOU' # 输出: hEllO
删除字符
echo "hello 123" | tr -d '0-9' # 输出: hello
压缩重复字符
echo "aaabbbccc" | tr -s 'a' # 输出: abbbccc
-
-
字符串截取:
-
从指定位置截取
${string:start:length}
- string:目标字符串。
- start:起始位置(从左往右数时,从 0 开始;从右往右数时,从 -1 开始)。
- length:截取长度(可省略,省略时截取到字符串末尾)。
-
按指定字符截取
截取右边字符(从匹配字符后开始截取):
${string#*chars} # 匹配第一个 chars ${string##*chars} # 匹配最后一个 chars
截取左边字符(从右往左):
${string%chars*} # 匹配从右往左第一个 chars ${string%%chars*} # 匹配从右往左最后一个 chars
示例:
url="https://blog.youkuaiyun.com/qq_41964263" # 从第一个 ":" 后截取 echo ${url#*:} # 输出 "//blog.youkuaiyun.com/qq_41964263" # 从最后一个 "/" 后截取 echo ${url##*/} # 输出 "qq_41964263" # 从从右往左第一个 "/" 前截取 echo ${url%/*} # 输出 "https://blog.youkuaiyun.com" # 从从右往左最后一个 "." 前截取 echo ${url%%/*} # 输出 "https:"
💥
*
是通配符的一种,表示任意字符串,如果不需要模糊匹配 chars 左边/右边的字符,那么也可以不写通配符*
url="https://blog.youkuaiyun.com/qq_41964263" echo ${url#https:} # 输出 "//blog.youkuaiyun.com/qq_41964263"
-
-
获取字符串长度
-
使用 ${#string}(推荐)
这是 Bash 内置的语法,直接通过变量名获取字符串长度,高效且简洁。
str="Hello World" length=${#str} echo "字符串长度为: $length"
-
默认值与条件赋值
-
默认值:如果变量未设置或为空,提供默认值:
user=${USER:-default_user} echo $user # 如果 USER 未设置,输出 default_user
-
条件赋值:如果变量未设置,报错并退出:
file=${1?"No file specified"} echo $file # 如果未传参数,脚本终止并提示错误
6. 只读变量与取消变量
只读变量
-
使用
readonly
声明只读变量,不可修改或删除:readonly PI=3.14 PI=3.1415 # 报错: cannot overwrite: readonly variable
取消变量
-
使用
unset
删除变量:unset var_name echo $var_name # 输出为空
7. 变量作用域
- 局部变量:仅在当前 Shell 脚本中有效。
- 环境变量:通过
export
导出后,对子进程可见。 - 父子 Shell 的继承:
- 子 Shell 可以继承父 Shell 的环境变量。
- 在子 Shell 中定义的变量,父 Shell 不可见。
8. 实际应用场景
处理脚本参数
#!/bin/bash
echo "欢迎 $1 到 $2!"
运行命令:
./welcome.sh Alice 优快云
输出:
欢迎 Alice 到 优快云!
动态文件路径
dir="/home/user"
file="data.txt"
full_path="${dir}/${file}"
cat $full_path
日志记录
log_file="/var/log/my_script.log"
echo "[$(date)] Script started" >> $log_file
总结
- Shell 变量是脚本编程的核心,灵活使用变量可以简化复杂操作。
- 注意变量作用域(本地 vs 环境变量)和引用方式(
$var
vs${var}
)。 - 利用特殊变量(
$#
,$@
,$?
)处理脚本参数和状态码。 - 字符串操作(替换、截取)和条件赋值能提升脚本的健壮性。
👍 时间不会回头,人生没有重来
😊 希望对你有帮助!