Bash脚本:通过位置参数控制多行字符串颜色输出的问题
问题分析与解决
你当前的printf写法确实存在隐患,核心问题出在"$@"和格式字符串的匹配逻辑上:
- 当
--后传入多个参数(比如多行文本拆成了多个位置参数),printf '%s%s%s\n' "$red" "$@" "$rst"会把$@的每个参数依次填充到格式串的%s占位符里,导致:- 颜色标记
$red只会作用于第一个参数,后续参数不会带上颜色 - 重置标记
$rst会被提前消耗,甚至出现在不恰当的位置,导致部分文本颜色无法重置 - 参数数量不匹配时,
printf会重复循环格式串,输出混乱内容
- 颜色标记
比如执行./script --chorn "第一行" "第二行",实际输出会是红色的第一行第二行加换行,随后单独输出重置标记加换行,完全不符合预期的每行带颜色的效果。
正确写法
要确保所有传入文本都被颜色包裹,且最后统一重置,推荐以下两种可靠方式:
方式1:分三次输出(最直观)
if (( chorn == 1 )); then printf '%s' "$red" # 先输出颜色控制码 printf '%s' "$@" # 输出所有内容,完整保留原格式(包括换行、空格) printf '%s\n' "$rst" # 最后输出重置码和换行 fi
方式2:合并参数后单次输出
如果想用一个printf命令完成,可以先把所有参数合并成完整字符串,再包裹颜色:
if (( chorn == 1 )); then printf '%s%s%s\n' "$red" "$(printf '%s' "$@")" "$rst" fi
额外优化:简化重复逻辑
你的脚本中多个分支的printf逻辑高度重复,仅颜色不同,可以简化代码减少冗余:
local color="" if (( chorn == 1 || ihorn == 1 )); then color="$red" elif (( clk == 1 || bell == 1 )); then color="$amb" fi if [[ -n "$color" ]]; then printf '%s' "$color" printf '%s' "$@" printf '%s\n' "$rst" fi
内容的提问来源于stack exchange,提问作者Dilna
相关产品推荐
相关产品推荐

