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
相关产品推荐
相关产品推荐

