Bash编写参数控制文本着色的colorText函数报bad substitution错误
错误原因
抛出bad substitution报错的核心原因是Bash变量展开语法使用错误:
- Bash 不支持
${$1}这种嵌套式的直接变量替换写法,解析器遇到这种格式时无法识别「先取$1的值作为变量名、再取对应变量值」的逻辑,会直接判定为非法语法抛错退出。 - 除此之外原代码还有两个逻辑问题:
- 函数只接收了颜色名参数,没有预留待着色文本的入参处理,也没有在输出末尾加颜色重置标记,会导致着色效果污染后续所有终端输出
- 脚本末尾
colorText $1的写法只能传递第一个脚本参数,带空格的待输出文本会被拆分截断。
修复实现
写法1:兼容低版本Bash的间接展开方案
完全适配你原有的常量定义方式,用Bash原生的间接引用语法${!变量名}实现动态取颜色值,兼容3.x版本的老Bash:
#!/bin/bash RED="\033[31m" GREEN="\033[0;32m" YELLOW="\033[0;33m" NC="\033[0m" # 终端颜色重置符,必须加避免后续输出被染色 colorText () { local target_color=$1 shift # 移除第一个参数(颜色名),剩余所有参数拼接为待输出文本 echo -e "${!target_color}$*${NC}" } # 把脚本接收到的所有参数完整传给函数,支持带空格的文本输入 colorText "$@"
这里的${!target_color}是Bash专门提供的间接引用语法:如果target_color存的值是另一个变量的名字(比如传入RED时,target_color的值就是字符串"RED"),该语法会直接返回对应变量(也就是RED)存储的内容。
写法2:关联数组实现(推荐,Bash 4.0+可用)
用关联数组维护颜色名和转义序列的映射关系,逻辑更直观,还方便扩展颜色、增加非法参数校验:
#!/bin/bash # 声明颜色映射关联数组 declare -A COLOR_MAP=( [RED]="\033[31m" [GREEN]="\033[0;32m" [YELLOW]="\033[0;33m" ) NC="\033[0m" colorText () { local color_seq=${COLOR_MAP[$1]} # 校验传入的颜色是否支持 if [[ -z $color_seq ]]; then echo "错误:不支持的颜色'$1',可选颜色为RED/GREEN/YELLOW" >&2 return 1 fi shift echo -e "${color_seq}$*${NC}" } colorText "$@"
调用方式
- 脚本内部调用:
colorText YELLOW "这是一段黄色提示文本" - 终端直接执行脚本:
./colorText RED "这是一段红色警告文本" - 注意待输出的文本如果带空格,需要用引号包裹,避免被Shell拆分为多个参数。
内容的提问来源于stack exchange,提问作者Hi I'm Irish
相关产品推荐
相关产品推荐

