在bash中的printf%s替换中高效地重用颜色代码

在bash中的printf%s替换中高效地重用颜色代码,bash,printf,Bash,Printf,当我只想给语句的某些部分添加颜色时,是否有一个printf快捷方式来避免必须定义每个%s 输入“$biwhite”“$color\u off”三次似乎是多余的。我认为您可以编写一个bash函数: biwhite=$(tput bold)$(tput setaf 7) color_off=$(tput sgr0) printf "%s$USER%s at %s$HOME%s has path %s$PATH%s" "$biwhite" "$color_off" "$biwhite" "$colo

当我只想给语句的某些部分添加颜色时,是否有一个
printf
快捷方式来避免必须定义每个
%s


输入
“$biwhite”“$color\u off”
三次似乎是多余的。

我认为您可以编写一个bash函数:

biwhite=$(tput bold)$(tput setaf 7)
color_off=$(tput sgr0)

printf "%s$USER%s at %s$HOME%s has path %s$PATH%s" "$biwhite" "$color_off" "$biwhite" "$color_off" "$biwhite" "$color_off"

另外,如果没有使用任何格式化功能,为什么要使用
printf

最好避免在
printf
的格式字符串中放置参数展开,以防它们也包含百分号。也就是说,参数替换提供了一种绕过某些重复性的方法

biwhite=$(tput bold)$(tput setaf 7)
color_off=$(tput sgr0)

whiten() {
  echo "$biwhite$1$color_off"
}

echo "$(whiten "$USER") at $(whiten "$HOME") has path $(whiten "$PATH")"
这不是万无一失的,但是
X
不太可能出现在
tput
的输出中。你可以选择一个更长的字符串来代替,但要付出更多的输入代价


不过,我担心在字符串中添加颜色代码本身就是一件痛苦的事情。

下面提供的是一个函数,它可以从第二个参数开始为其他每个参数着色。(因此,可以通过在第一个位置传递非空字符串来提供非彩色前缀,或者通过将其保留为空来提供彩色前缀,如下所示)

值得注意的是,除了用于说明目的的
tput
调用之外,此代码的执行中不涉及子shell。因此,虽然冗长,但执行的开销非常低

w="${biwhite}X${color_off}"

printf "%s at %s has path %s" "${w/X/$USER}" "${w/X/$HOME}" "${w/X/$PATH}"
这可以通过向单个调用传递
start\u color
end\u color
值来定制;例如:

biwhite=$(tput bold)$(tput setaf 7)
color_off=$(tput sgr0)

# colorize every other argument, starting from the 2nd.
colorize_words() {
  local start_color end_color
  : "${start_color:=$biwhite}" "${end_color:=$color_off}"
  while (( $# )); do
    printf '%s' "$1"
    shift || break
    printf '%s%s%s' "$start_color" "$1" "$end_color"
    shift || break
  done
  printf '\n'
}

colorize_words "" "$USER" " at " "$HOME" " has path " "$PATH"

真正的问题是,为什么要使用
echo
而不是
printf
?此外,您建议OP用大量子shell替换好的代码。。。这不是很好。在一些常见情况下,使用
printf
而不是
echo
是由…
echo
直接建议的。在一些常见情况下,标准未定义echo的行为(并且实现之间存在差异),特别是在传递的参数可能包含反斜杠文字的任何情况下。值得注意的是,在启用和不启用
xpg_echo
标志的情况下(以及在启用和不启用
posix
标志以及
xpg_echo
的情况下),bash的行为是这些分歧点之一。这不是一个不合理的问题——许多其他语言都有在格式字符串中引用特定位置参数的方法。比如
zsh
?Ducks你不应该把
$USER
$HOME
$PATH
放在格式字符串中,因为你可能不想把
$biwhite
$color\u关闭
放在格式字符串中:如果它们包含百分号,你就有问题了。每个人都给出了非常好的答案!我之所以选择@chepner,是因为我认为答案“恐怕在字符串中添加色码本身就是痛苦的。”可能是最有用的答案:|非常感谢你,查尔斯。你总是有很好的答案。
# this prints every other argument in red
start_color=$(tput setaf 1) colorize_words "hello " "cruel " world