Bash中$*与$@参数扩展无法匹配空格的解决方案求助
在Bash中移除$*开头的"x "的解决方案
你遇到的这个问题确实是Dash和Bash在参数扩展处理逻辑上的差异导致的——在Dash里,${*#x }能直接匹配并移除$*开头的"x ",得到无多余空格的hello world;但Bash对$*的扩展规则不一样,它会先把所有参数用IFS的第一个字符连接成字符串,再进行模式匹配,这就导致直接用${*#x }这类写法没法正确命中目标前缀。
下面给你几个不用临时变量(或仅临时修改环境变量)的可行解决方案:
方案1:数组切片跳过第一个参数(最直接)
如果你的场景是确定第一个参数就是x,直接用数组切片从第二个参数开始取所有内容即可:
set -- x hello world echo "<${*:2}>" # 输出:<hello world>
${*:2}表示从第二个参数开始的所有参数,会自动用IFS(默认是空格)连接成字符串,完美符合你的需求。
方案2:临时修改IFS配合$@前缀匹配
如果不确定第一个参数是不是x,只是想移除拼接后字符串开头的x ,可以临时把IFS设为空,让$@直接拼接成无分隔的字符串,再做前缀匹配:
set -- x hello world OLD_IFS="$IFS" IFS='' echo "<${@#x }>" IFS="$OLD_IFS" # 输出:<hello world>
当IFS为空时,$@会把所有参数无缝拼接,此时${@#x }就能精准匹配并移除开头的x ,之后再恢复原来的IFS即可。
方案3:开启扩展正则做前缀替换
如果你需要更灵活的模式匹配,可以开启Bash的extglob选项,用前缀替换语法:
set -- x hello world shopt -s extglob echo "<${*/#x /}>" # 输出:<hello world>
这里的/#是Bash的特殊替换标记,表示仅匹配字符串开头的模式,x 就是我们要移除的前缀,开启extglob后这个逻辑就能正常工作。
补充:为什么Dash能行而Bash不行?
Dash对${*#pattern}的处理逻辑更简单:它会把$*扩展成用空格连接的字符串后,直接对整个字符串做前缀匹配;而Bash在处理$*的模式匹配时,内部的参数分隔处理会干扰开头带空格的模式匹配,导致${*#x }没法正确识别开头的x 。
内容的提问来源于stack exchange,提问作者Adam Katz
相关产品推荐
相关产品推荐

