首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >Linux shell 变量详解

Linux shell 变量详解

原创
作者头像
用户12619466
修改2026-07-17 23:05:37
修改2026-07-17 23:05:37
180
举报

shell变量

  1. var_name="runoob",变量名和等号之间不能有空格,因为空格通常用于分隔命令和参数
  2. 使用变量:$var_name${var_name},加大括号是为了帮助解释器识别变量的边界。$ 相当于从变量中取值(解引用),不加 $ 则表示变量本身
  3. 只读变量:readonly var_name,变量值不可被改变
  4. 删除变量:unset var_name,删除后不能再次使用,不能删除只读变量

变量类型

字符串变量
  • 使用单引号'或双引号"定义,var_name='zmy' var_name="zmy"

ℹ️undefined单引号中的任何字符都会原样输出,其中的变量是无效的,单引号字符串内不能出现一个单独的单引号(转义也不行)但可成对出现,作为字符串拼接使用:

代码语言:shell
复制
var1='zmy_'$var_name'_flm' # 输出 zmy_runoob_flm
var2='zmy_$var_name_flm' # 输出 zmy_$var_name_flm
  • 双引号中可以有变量,可以出现转义字符:var1="Hi, "$var_name"! \n" # 输出 Hi, runoob var2="Hi, ${var_name}! \n" # 输出 Hi, runoobstring="runoob is a great site" echo expr index "$string" io # 输出 4
  • 获取字符串长度:${#var_name},等价于${#var_name[0]}
  • 提取子字符串:${var_name:1:2}输出un
  • 查找子字符串:
整数变量
  • declare -i my_int=42
代码语言:shell
复制
# 使用 (( )) 算术表达式(推荐)
a=2
((a++))      # a 自增 1 → a=3
((a--))      # 自减
((a += 1))   # 等价于 a = a + 1
((a = a + 1))

# 使用 $(( )) 算术扩展
a=2
a=$((a + 1))   # a=3
a=$((a * 2))   # a=6

# 使用 let 命令(较老,不推荐)
a=2
let a=a+1
let "a += 1"   # 带空格时需加引号
数组(不支持多维数组)
  • 整数索引数组:my_array=(1 2 3 4 5 6)
  • 关联数组:declare -A my_array, my_array['name']='zmy',my_array['age']=30
代码语言:shell
复制
# 获取数组的某个值
value=${my_array[n]}

# 使用 @ 或 * 获取数组中所有元素
${my_array[@]}
${my_array[*]}

# 使用 ! 获取数组中所有键
${!my_array[@]}
${!my_array[*]}

# 获取数组元素的个数
length=${#my_array[@]}; 
length=${#my_array[*]}

# 获取单个元素的长度
length=${#my_array[n]}

# 判断关联数组中是否存在键
if [[ -n "${my_array[$key]+exists}" ]]; then
    echo "$key 存在"
fi

if [[ -v "my_array[$key]" ]]; then
    echo "$key 存在"
fi

# 判断普通数组中是否存在值
[[ "${my_array[*]}" =~ "$value" ]] && echo "存在" || echo "不存在"
mapfile
  • 在 Bash 4.0 及以上版本中,mapfile 是一个强大的内置命令,用于将文件或标准输入的内容按行读入数组。它等价于 readarray,语法和功能完全一致。
代码语言:shell
复制
# 如果不指定数组名,数据将默认存储到 MAPFILE 数组中。
mapfile [选项] 数组名 < 输入源
# 或
mapfile [选项] 数组名 文件名
  • 常用选项
  • -n count 最多读取 count 行
  • -O origin 从数组索引 origin 开始赋值(默认 0)
  • -s count 跳过前 count 行
  • -t 删除每行末尾的换行符(默认行为)
  • -d DELIM 指定行分隔符(默认是换行符)
  • -u fd 从文件描述符 fd 读取(默认 0)
  • -C callback 每读 callback 行调用一次命令
  • -c quantum-C 搭配,指定调用频率,每读取 quantum 行执行一次回调(包括当前行)

⚠️ 回调是在读取过程中触发,不是读取完成后 每次回调时,数组只包含当前已读取的行 执行回调时,会传递两个参数 $1: 当前正在读取的行号,从 0 开始,$2: 当前正在读取的行内容 利用回调时的数组长度(等于 $1 参数)

内置特殊变量
命令行参数变量
  • $0 脚本名称
  • $1-$9 第1-9个位置参数
  • ${10} 第10个参数(需要大括号)
  • $# 参数个数
  • $@ 所有参数,每个都是独立字符串,如果 "$@" 则以 "$1" "$2" ... "$n" 的形式输出所有参数
  • $* 所有参数,作为一个字符串,如果是 "$*" 则以 "$1 $2 ... $n" 的形式输出所有参数进程和状态变量
  • $$ 当前进程PID
  • $! 最后一个后台进程的PID
  • $? 上一个命令的退出状态码
  • $_ 上一个命令的最后一个参数
  • $- 当前shell选项标记
  • !! 上一条命令脚本信息变量
  • $BASH Bash的完整路径
  • $BASH_VERSION Bash版本
  • $BASH_VERSINFO[0-6] Bash版本信息数组
  • $BASH_SOURCE 当前执行的源文件(脚本)路径
  • $BASH_SUBSHELL 子shell层级执行环境变量
  • $LINENO 当前在脚本中的行号
  • $FUNCNAME 当前函数名(数组,[0] 是当前函数)
  • $BASH_COMMAND 当前正在执行的命令
  • $PIPESTATUS 管道中每个命令的退出状态数组
  • $SECONDS 脚本运行秒数
  • $RANDOM 随机数(0-32767)
  • $REPLY read命令默认读取的变量
  • $OPTARG getopts的选项参数
  • $OPTIND getopts的选项索引行和文件描述符
  • $COLUMNS 终端列数
  • $LINES 终端行数
  • $UID 当前用户UID
  • $EUID 当前有效用户UID
  • $GROUPS 用户所属组数组调试相关变量
  • $BASH_XTRACEFD 用于set -x输出的文件描述符
  • $BASH_LINENO 函数调用栈的行号数组
  • $BASH_ARGC 函数参数个数数组
  • $BASH_ARGV 函数参数值数组扩展和匹配变量
  • $IFS 内部字段分隔符(默认是空格、制表符、换行)
  • $GLOBIGNORE 通配符忽略模式
  • $BASH_REMATCH 正则表达式匹配结果数组
  • $BASH_ALIASES 别名数组
  • $BASH_CMDS 命令哈希表
注释
  • 单行注释:# 这是一个注释
  • 多行注释:冒号:是空命令,内容不会执行
代码语言:shell
复制
:<<EOF(EOF也可以使用其他符号:COMMENT ' !)
注释内容
注释内容
注释内容
EOF

: '
这是注释的部分。
可以有多行内容。
'

参数扩展

shell命令执行顺序

  1. 分词 (Tokenization):分割成 tokens: echo, "当前目录: $PWD", *.txt
  2. 展开 (Expansion):参数展开在这里发生

a. 大括号展开 {}

b. 波浪号展开 ~

c. 参数展开 $

d. 命令替换 $()

e. 算术展开 $(( ))

f. 单词分割

g. 文件名展开 * ? [...]

  1. 引用移除 (Quote Removal)
  2. 命令执行 (Execution)
  3. 参数扩展提供了多种方式来修改和提取变量的内容,如果 parameter 是数字,则是参数扩展;如果 parameter 是字符串,则是变量扩展;如果 parameter 是数组,遵循数组的扩展规则;parameter 还可以是 @, *, #, ?, - 等,参考特殊参数的扩展。
  4. shell 变量扩展发生在命令执行前
代码语言:shell
复制
# 无引号:Shell 扩展
echo *.txt           # Shell 扩展
# 单引号:完全字面
echo '*.txt'         # 输出: *.txt
# 双引号:变量扩展,但通配符不扩展
echo "$HOME/*.txt"   # 输出: /home/user/*.txt

ℹ️undefined除了 ${variable:=word} 和 ${variable::=word}(强制修改变量为 word 无论原变量是否为空,Bash 4.4+ 新增)之外,其他变量扩展不会修改变量的值,仅是返回扩展结果

  • 直接扩展和间接扩展 a=b; b=123;
    • echo ${a} 基本扩展,输出结果为 b
    • echo ${!a} 间接参数扩展,输出结果为变量 b 的值 123${!var}将参数扩展为变量的值,在处理变量名作为字符串时很有用
    • 如果 b 是一个名称引用(nameref),则不会发生间接扩展,还是输出 b
  • 变量引用
    • ${variable} 或 $variable 直接引用变量的值
  • 设置默认值
    • ${variable:-word} - 如果变量 variable 已被设置且非空,则展开为变量的值;否则,展开为 word
    • ${variable:=word} - 类似于 ${variable:-word},但是还会将 word 的值赋给变量 variable
    • ${variable:+word} - 如果变量 variable 已被设置且非空,则展开为 word;否则,什么也不做。
    • ${variable:?word} - 如果变量 variable 已被设置且非空,则展开为变量的值;否则,打印错误消息至标准错误并退出 shell,错误消息包含 word
  • 字符删除
    • ${variable#pattern} 删除 variablepattern 匹配的开头最短部分。
    • ${variable##pattern} 删除 variablepattern 匹配的开头最长部分。
    • ${variable%pattern} 删除 variablepattern 匹配的结尾最短部分。
    • ${variable%%pattern} 删除 variablepattern 匹配的结尾最长部分。
    • pattern 是 Glob 模式
      • ? 匹配任何一个字符。
      • * 匹配任意数量的字符(包括零个字符)。
      • [...] 匹配括号内的任何一个字符。例如,[abc] 匹配 'a'、'b' 或 'c'
      • {a,b,c} 匹配 a 或 b 或 c

ℹ️

pattern 必须能够匹配开头(对于 % )或者结尾(对于 # ),如果只匹配了中间部分则无法删除

  • 字符替换
    • ${variable/pattern/string} 替换变量值 variable 的第一次出现的 patternstring
    • ${variable//pattern/string} 替换变量值 variable 中所有出现的 patternstring
    • ${variable/#pattern/string}:如果变量 variable 值以 pattern 开头,则将其替换为 string
    • ${variable/%pattern/string}:如果变量 variable 值以 pattern 结尾,则将其替换为 string

ℹ️ 其中 /string 部分可省略,表示替换为空,即删除,例如 ${url//:*} 删除 :之后的所有内容

  • 子字符串截取
    • ${variable:start:length} - 截取变量值 variable 的子字符串,从索引 start 开始(从0开始计数),长度为 length 字符。
    • ${variable:start} - 截取变量值 variable 的子字符串,从索引 start 开始(从0开始计数)直到末尾。
  • 大小写转换
    • ${variable,,} - 将变量值 variable 转换为小写。
    • ${variable^^} - 将变量值 variable 转换为大写。
    • ${parameter^pattern}${parameter^^pattern} 用于将变量值中的匹配部分转换为大写,分别转换第一个匹配和所有匹配。
    • ${parameter,pattern}${parameter,,pattern} 用于将变量值中的匹配部分转换为小写,分别转换第一个匹配和所有匹配。
特定操作( Bash 4.4 及以上版本)${variable@operator} operator 取值:
  • U 全大写
  • u 首字母大写
  • L 全小写
  • K 显示变量的赋值语句格式,字符串会被引号包裹
  • Q 转义字符生成
  • E 转义字符展开
  • P 提示符展开
  • A 显示变量的声明语句
  • K 数组变量名和值
  • k 数组变量名和值
  • a 返回变量属性值, 表示为一系列标志:
    • -:变量既没有被引号引用,也不是数组。
    • q:变量被单引号引用。
    • Q:变量被双引号引用。
    • x:变量是被解释的。
    • X:变量是被不被解释的。
    • @:变量是数组或者关联数组。
    • A:变量是被赋值的(assigned)。

欢迎大家关注【扶锐随笔】

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • shell变量
    • 变量类型
      • 字符串变量
      • 整数变量
      • 数组(不支持多维数组)
      • mapfile
      • 内置特殊变量
      • 注释
  • 参数扩展
    • shell命令执行顺序
      • 特定操作( Bash 4.4 及以上版本)${variable@operator} operator 取值:
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档