Shell 参数展开产生替代值
参数展开根据 Shell 参数产生一个值,随后命令才收到展开后的参数。它可以提供默认值、拒绝缺失配置,或者删除字符串的一部分,不必为这些操作启动额外进程。但“执行命令前展开”并不等于“初次解析脚本时就求值”:函数在被调用时读取变量当前的内容,函数定义之后修改变量,会影响后续调用。区分解析、展开和执行,才能解释为什么相同的表达式在不同时间产生不同结果。 冒号把空字符串也计入缺值条件。普通默认值不改保存状态,赋值默认值会回写。Shell 模式删除改变结果,不改原变量,也不访问文件系统。 默认值要区分未设置与空字符串 ${setting:-default} 在变量未设置或者为空时使用默认值;${setting-default} 只处理未设置的情况,保留调用者明确传入的空字符串。冒号改变的是配置语义,不能当成随意省略的标点。例如空字符串可能表示关闭某个前缀,擅自用默认值替换就会改变用户的选择。${setting:+enabled} 只在变量已设置且非空时产生替代文本,去掉冒号后,已设置但为空也满足条件。 普通默认值展开不会修改变量本身。${setting:=default} 才会在选中默认分支时把结果存进变量,之后再读取就能看到新值。${setting:?message} 则在变量未设置或为空时把诊断写到标准错误,并让非交互 Shell 以非零状态退出。去掉冒号后,这两个运算符也只检查是否设置。应当先确定调用约定:允许为空、允许省略,还是必须提供,然后选择相应形式,而不是把所有配置问题都掩盖成一个默认值。 花括号还负责把变量名与相邻文本分开。"${prefix}_suffix" 是给变量内容追加后缀,"$prefix_suffix" 却读取另一个变量。用几个配置拼文件名时,看似缺值的问题可能只是变量名边界写错。应分别检查各个组成部分,再排查最终路径;一个语法完全合法的字符串,也可能混入来自错误变量的内容。 模式处理字符串,不访问文件 ${name#pattern} 与 ${name##pattern} 分别删除最短和最长匹配前缀;对应的后缀运算符是 % 与 %%。这里使用 Shell 模式,不是正则表达式。匹配不到时保留原字符串,匹配成功也不会自动回写原变量。斜杠在这里就是普通的文本内容,这些运算不会查询目录、确认文件存在或者解析符号链接,因此不能用一次字符串截取证明路径安全。 ...