You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Shell脚本中%与%%的差异及工作原理解析:Bash实例

Bash参数扩展:#/## 和 %/%% 的差异

嘿,这个问题问得特别到位!虽然在你的测试案例里两组符号返回了相同结果,但它们的匹配逻辑本质完全不同——核心区别在于「最短匹配」和「最长匹配」(也就是大家常说的非贪婪/贪婪匹配)。下面我给你拆解清楚:

先搞懂后缀匹配:% vs %%

这俩都是从字符串末尾开始匹配并删除内容,但匹配范围不一样:

  • ${变量%匹配模式}:删除最短的匹配后缀——从字符串末尾往前找,找到第一个符合模式的位置就停止,只删掉这部分。
  • ${变量%%匹配模式}:删除最长的匹配后缀——从字符串末尾往前找,找到最左边的符合模式的位置,删掉从那个位置到末尾的所有内容。

举个直观的例子,当变量有多个相同后缀时:

t="hello.txt.txt"
echo "${t%.txt}"   # 输出:hello.txt(只删掉最后一个.txt)
echo "${t%%.txt}"  # 输出:hello(删掉从第一个.txt到末尾的所有内容)

再看前缀匹配:# vs ##

这俩是从字符串开头开始匹配并删除内容,同样是最短/最长的区别:

  • ${变量#匹配模式}:删除最短的匹配前缀——从字符串开头往后找,找到第一个符合模式的位置就停止,只删掉这部分。
  • ${变量##匹配模式}:删除最长的匹配前缀——从字符串开头往后找,找到最右边的符合模式的位置,删掉从开头到那个位置的所有内容。

同样用多匹配点的例子演示:

t="abc.def.ghi.txt"
echo "${t#*.}"     # 输出:def.ghi.txt(只删掉第一个.之前的abc)
echo "${t##*.}"    # 输出:txt(删掉最后一个.之前的所有内容)

为什么你的例子里结果相同?

因为你测试的字符串t="hello.txt"里,只有一个.txt后缀,也只有一个*.前缀——不管是最短还是最长匹配,能删的只有这一处,所以结果自然一致。但当字符串里有多个符合模式的片段时,两组符号的差异就立刻显现了。

核心规则总结

  • #:开头最短匹配删除
  • ##:开头最长匹配删除
  • %:结尾最短匹配删除
  • %%:结尾最长匹配删除

这些都是Bash内置的参数扩展功能,用通配符(比如*代表任意字符)做匹配,不用调用外部命令就能快速处理字符串,效率特别高~

内容的提问来源于stack exchange,提问作者Naveen Dennis

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 09:18:33