跳至正文
老丹的足迹 —— 代码写给机器,游记写给自己,感悟写给时间
老丹的足迹 老丹的足迹
老丹的足迹 老丹的足迹
  • 首页
  • 示例页面
  • 首页
  • 示例页面
老丹的足迹 老丹的足迹
老丹的足迹 老丹的足迹
  • 首页
  • 示例页面
  • 首页
  • 示例页面

Bash 变量内容操作完全指南

前言

Bash 提供了极为丰富的变量内容操作功能,涵盖了删除、替换、替代、默认值处理、大小写转换、子串提取等各个方面。这些操作统称为 参数扩展(Parameter Expansion),是 Bash 脚本编程中最常用也最强大的特性之一。

本文将从零开始,系统性地整理所有与变量内容相关的操作,并区分哪些是基础必会、哪些是进阶内容、哪些属于高级特性。

第一部分:删除操作

删除操作用于从变量内容中移除匹配特定模式的字符串。

1.1 前缀删除(从开头匹配)

语法名称匹配方式示例
${var#pattern}最小匹配删除开头最短匹配var="abc123abc" → ${var#a*c} → 123abc
${var##pattern}最大匹配删除开头最长匹配var="abc123abc" → ${var##a*c} → (空)

典型用途:

  • 提取文件名:${path##*/}(删除最后一个斜杠之前的所有内容)
  • 去除前缀:${string##*:}(删除最后一个冒号之前的所有内容)

1.2 后缀删除(从结尾匹配)

语法名称匹配方式示例
${var%pattern}最小匹配删除结尾最短匹配var="abc123abc" → ${var%a*c} → abc123
${var%%pattern}最大匹配删除结尾最长匹配var="abc123abc" → ${var%%a*c} → (空)

典型用途:

  • 去除文件扩展名:${filename%.*}(删除最后一个点及之后)
  • 去除后缀:${string%% *}(删除第一个空格及之后)

1.3 删除操作的模式说明

所有 pattern 都使用 通配符(globbing) 语法,而非正则表达式:

  • *:匹配任意字符串(包括空串)
  • ?:匹配任意单个字符
  • [...]:匹配方括号内的任一字符,如 [a-z]、[0-9]
  • [^...]:匹配不在方括号内的任一字符

第二部分:替代操作

替代操作用新字符串替换匹配到的内容。

2.1 基础替代

语法名称行为示例
${var/old/new}单次替换替换第一个匹配var="abc123abc" → ${var/abc/XYZ} → XYZ123abc
${var//old/new}全局替换替换所有匹配var="abc123abc" → ${var//abc/XYZ} → XYZ123XYZ

2.2 锚定替代

语法名称行为示例
${var/#old/new}开头替换仅当匹配开头时替换var="abc123abc" → ${var/#abc/XYZ} → XYZ123abc
${var/%old/new}结尾替换仅当匹配结尾时替换var="abc123abc" → ${var/%abc/XYZ} → abc123XYZ

2.3 删除形式的替代(替换为空)

省略 new 部分,相当于删除匹配内容:

语法行为示例
${var/pattern}删除第一个匹配var="abc123abc" → ${var/abc} → 123abc
${var//pattern}删除所有匹配var="abc123abc" → ${var//abc} → 123
${var/#pattern}仅开头匹配时删除var="abc123abc" → ${var/#abc} → 123abc
${var/%pattern}仅结尾匹配时删除var="abc123abc" → ${var/%abc} → abc123

第三部分:默认值替换(回退赋值)

这部分用于处理变量未定义或为空的情况。每个操作都有带冒号和不带冒号两个版本,区别在于是否检查空字符串。

3.1 替换(不修改变量本身)

语法行为说明
${var-expr}未定义时替换仅当 var 未定义时,用 expr 代替
${var:-expr}未定义或空时替换当 var 未定义或为空时,用 expr 代替

区别示例:

unset var           # var 未定义
echo ${var-default}   # 输出 default
echo ${var:-default}  # 输出 default

var=""              # var 已定义但为空
echo ${var-default}   # 输出(空)
echo ${var:-default}  # 输出 default

var="hello"
echo ${var-default}   # 输出 hello
echo ${var:-default}  # 输出 hello

3.2 赋值(修改变量本身)

语法行为说明
${var=expr}未定义时赋值仅当 var 未定义时,将 expr 赋值给 var
${var:=expr}未定义或空时赋值当 var 未定义或为空时,将 expr 赋值给 var

3.3 报错退出

语法行为说明
${var?expr}未定义时报错仅当 var 未定义时,输出 expr 错误并退出
${var:?expr}未定义或空时报错当 var 未定义或为空时,输出 expr 错误并退出

3.4 条件替换(检测是否已定义)

语法行为说明
${var+expr}已定义时替换仅当 var 已定义时,用 expr 代替(否则为空)
${var:+expr}非空时替换仅当 var 非空时,用 expr 代替(否则为空)

典型用途:检测变量是否被显式设置(包括空字符串)

if [ -n "${1+set}" ]; then
    echo "用户传入了第一个参数(可能为空字符串)"
fi

第四部分:大小写转换

Bash 4.0 引入,用于改变字母的大小写形态。

语法行为示例
${var^}首字母转大写var="hello world" → ${var^} → Hello world
${var^^}全部转大写var="hello world" → ${var^^} → HELLO WORLD
${var,}首字母转小写var="HELLO" → ${var,} → hELLO
${var,,}全部转小写var="HELLO" → ${var,,} → hello
${var~}首字母大小写反转var="Hello" → ${var~} → hello
${var~~}全部大小写反转var="Hello World" → ${var~~} → hELLO wORLD

高级用法:模式限定

这些操作符可以接受一个可选的模式参数,只转换匹配的部分:

var="hello world"
echo ${var^^[aeiou]}      # 只转元音:hEllO wOrld
echo ${var^[aeiou]}       # 只转匹配的第一个元音:hEllo world?实际行为需测试

第五部分:变换操作

Bash 4.4 引入的高级特性,通过 @ 操作符实现。

语法行为示例
${var@U}转大写${var@U} 等同于 ${var^^}
${var@L}转小写${var@L} 等同于 ${var,,}
${var@Q}转义为可重用的引用格式var="hello 'world'" → ${var@Q} → 'hello '\''world'\'''
${var@E}展开转义序列var="hello\nworld" → ${var@E} → 实际换行
${var@P}按提示符规则展开支持 \u(用户名)、\h(主机名)等
${var@A}显示赋值语句输出 declare -- var="value" 格式

第六部分:子串提取

从变量中截取部分内容。

语法行为示例
${var:offset}从 offset 取到末尾var="hello.txt" → ${var:2} → llo.txt
${var:offset:length}从 offset 取 length 个var="hello.txt" → ${var:2:3} → llo
${var: -n}取末尾 n 个字符var="hello.txt" → ${var: -4} → .txt

注意事项:

  • offset 从 0 开始计数
  • 取末尾字符时,: 后面必须有空格,以避免与 ${var:-default} 语法混淆

第七部分:间接扩展

通过变量名引用另一个变量的值。

语法行为示例
${!var}间接引用ref="name"、name="world" → ${!ref} → world

典型用途:

  • 动态变量名处理
  • 配置系统(当变量名由运行时决定)

第八部分:模式匹配增强(extglob)

通过 shopt -s extglob 开启扩展模式匹配,获得更强大的模式语法:

模式含义示例
?(pattern)匹配 0 或 1 次abc?(def) 匹配 abc 或 abcdef
*(pattern)匹配 0 或多次abc*(def) 匹配 abc、abcdef、abcdefdef…
+(pattern)匹配 1 或多次abc+(def) 匹配 abcdef、abcdefdef…
@(pattern1|pattern2)匹配其中之一abc@(def|xyz) 匹配 abcdef 或 abcxyz
!(pattern)匹配非该模式abc!(def) 匹配除 abcdef 外的任意内容

开启方式:

shopt -s extglob
var="abc123def"
echo ${var//+(digit)/}   # 删除连续数字(假设定义了 digit 模式)

完整速查表

分类操作符一句话说明
删除(前缀)#从开头删除最短匹配
##从开头删除最长匹配
删除(后缀)%从结尾删除最短匹配
%%从结尾删除最长匹配
替代/替换第一个匹配
//替换所有匹配
/#仅开头匹配时替换
/%仅结尾匹配时替换
默认值(不赋值)-未定义时替换
:-未定义或空时替换
默认值(赋值)=未定义时赋值
:=未定义或空时赋值
报错?未定义时报错
:?未定义或空时报错
条件替换+已定义时替换
:+非空时替换
大小写^首字母大写
^^全部大写
,首字母小写
,,全部小写
~首字母大小写反转
~~全部大小写反转
变换@U大写转换(Bash 4.4+)
@L小写转换(Bash 4.4+)
@Q转义引用(Bash 4.4+)
@E展开转义序列(Bash 4.4+)
@P提示符展开(Bash 4.4+)
@A显示赋值语句(Bash 4.4+)
子串:offset截取到末尾
:offset:len截取指定长度
: -n取末尾 n 个
间接!var间接引用

难易程度分级

基础必会(日常使用频率极高)

  • ${var#pattern}、${var%pattern}:去路径、去扩展名
  • ${var/old/new}:简单的字符串替换
  • ${var:-default}:设置默认值
  • ${var:offset}、${var:offset:length}:截取子串

进阶掌握(提升脚本效率)

  • ${var##pattern}、${var%%pattern}:最长匹配删除
  • ${var//old/new}:全局替换
  • ${var^}、${var^^}、${var,}、${var,,}:大小写转换
  • ${var: -n}:取末尾字符
  • ${var=default}、${var:?error}:赋值和错误处理

高级特性(特定场景使用)

  • ${!var}:间接引用
  • ${var@U}、${var@L}、${var@Q} 等变换操作
  • extglob 扩展模式匹配
  • ${var+expr}、${var:+expr} 条件替换的精妙用法

总结

Bash 的变量内容操作看似繁多,但大多数都有清晰的命名逻辑:

  • # 和 % 让人联想到行首(# 在键盘左侧)和行尾(% 在右侧)——虽然是民间记忆法
  • 单个字符表示最小匹配,双字符表示最大匹配
  • 冒号 : 的加入表示同时检查空字符串
  • 大小写转换用 ^(上箭头表示大写)、,(下箭头?表示小写)、~(取反)

掌握这些操作,你将能够用极其简洁的代码完成原本需要调用 sed、awk、cut、tr 等外部命令才能实现的字符串处理任务。这不仅能提升脚本执行效率(避免创建子进程),也能让代码更加清晰易读。

最重要的建议:不需要死记硬背所有操作符,先熟练掌握 #、%、/、:- 这四个最常用的,然后在使用过程中逐步学习和扩展。这份文档可以作为随时查阅的参考手册。

作者

老丹

关注我
其他文章
上一个

usbutils:Linux下USB设备查看与调试的完整指南

下一个

Bash 数组完全指南:从设计思想到实战应用

关于博主

    老丹是一名C/C++后台开发工程师,信奉“无抽象不设计,无性能不生产”。

  • 技术栈:Modern C++、Linux环境编程、多线程/并发、网络编程等。
  • 信条:能用constexpr解决的问题绝不拖到运行时,能靠RAII避免的泄漏绝不写析构。
  • 正在填坑:从解封装到渲染的C++全链路实现,正在驯服FFmpeg与H.264/H.265。
  • 输出原则:这里的每一段代码都经过-Wall -Wextra -Werror -O2的洗礼。

搜索

近期文章

  • Bash命令行参数完全指南 2026年6月17日
  • Bash 数组完全指南:从设计思想到实战应用 2026年6月16日
  • Bash 变量内容操作完全指南 2026年6月16日
  • usbutils:Linux下USB设备查看与调试的完整指南 2026年6月16日
  • MQTT协议完全指南:从核心概念到实践应用 2026年6月16日
  • ICO文件格式完全解析 2026年6月15日

文章分类

  • C/C++开发 (10)
  • Linux工具包 (6)
  • Linux服务配置 (7)
  • Shell脚本 (3)
  • 计算机理论 (9)
联系我们:📍 地址:中国·广东省深圳市   |   ✉️ 邮箱:support@tanglinux.com   |   💬 QQ:870866607
版权所有:老丹的足迹粤ICP备2026061170号-1       公安备案图标 粤公网安备44030002013274号