printf 转义代码未在 Bash 脚本中格式化
printf escape code not formatting in Bash script
我最近开始使用 Bash,主要是用它来自定义我的 .profile
,我 运行 遇到了 printf
的问题命令。
在我的脚本文件夹中,我设置了一个关联数组,以便于使用 ANSI 颜色代码:
#!/usr/bin/env bash
declare -A fcolors=(
[black]='\e[30m'
[red]='\e[31m'
[green]='\e[32m'
[yellow]='\e[33m'
[blue]='\e[34m'
[magenta]='\e[35m'
[cyan]='\e[36m'
[gray]='\e[90m'
# LIGHT COLOURS
[lgray]='\e[37m'
[lred]='\e[91m'
[lgreen]='\e[92m'
[lyellow]='\e[93m'
[lblue]='\e[94m'
[lmagenta]='\e[95m'
[lcyan]='\e[96m'
[white]='\e[97m'
[default]='\e[0m' )
我还在另一个文件中有一个脚本,用于将输出集中在终端上,诚然,我从 GitHub:
上的某人的指南中借用了该脚本
#!/usr/bin/env bash
# original script by TrinityCoder
# USAGE: printcen "center text" "filler text"
function printcen {
[[ $# == 0 ]] && return 1
declare -i TERM_COLS="$(tput cols)"
declare -i str_len="${#1}"
[[ $str_len -ge $TERM_COLS ]] && {
echo "";
return 0;
}
declare -i filler_len="$(( (TERM_COLS - str_len) / 2 ))"
[[ $# -ge 2 ]] && ch="${2:0:1}" || ch =" "
filler=""
for (( i = 0; i < filler_len; i++ )); do
filler="${filler}${ch}"
done
printf "%s%s%s" "$filler" "" "$filler"
[[ $(( (TERM_COLS - str_len) % 2 )) -ne 0 ]] && printf "%s" "$ch"
printf "\n"
return 0
}
最后,我找到了导致问题的线路本身。我只用这一行试过,所以这里是:
#!/usr/bin/env bash
source ~/.scripts/bagcolors
source ~/.scripts/printcen
printcen " ${fcolors[cyan]} ----========================---- ${fcolors[default]}" " "
当我 运行 文件时,printcen
函数似乎只是准确地打印颜色代码,包括转义序列,就好像它只是一个常规字符串一样。到目前为止,我已经尝试在颜色代码和文本本身之间放置空格,但这似乎没有任何改变。
如有任何帮助,我们将不胜感激。
您的方法存在的问题是您会将 不可见 个字符计为字符串的一部分。
执行此操作(在按照@gniourf_gniourf 指示修复转义序列后)
l=$(printcen '----========================----')
printf '%s%s%s\n' "${fcolors[cyan]}" "$l" "${fcolors[default]}"
第二个问题是您通过 "%s"
转换说明符将 ANSI 转义符放入 printcen
中的 printf
而不是将它们作为格式字符串的一部分。您有两个选择:
printf "%s%s" "$filler" "$filler"
(以上为首选方式)
或者,只需使用命令替换来扩展转义:
printf "%s%s%s" "$filler" $(printf "") "$filler"
(需要一个额外的 subshell)
任何一种方法都应该有效。虽然一开始就使用 ANSI 转义符是值得的,但并不能真正保证它们在 VT 终端仿真之外工作。因此,您使用它们的脚本将不可移植。 (但它们很适合装饰使用)
我最近开始使用 Bash,主要是用它来自定义我的 .profile
,我 运行 遇到了 printf
的问题命令。
在我的脚本文件夹中,我设置了一个关联数组,以便于使用 ANSI 颜色代码:
#!/usr/bin/env bash
declare -A fcolors=(
[black]='\e[30m'
[red]='\e[31m'
[green]='\e[32m'
[yellow]='\e[33m'
[blue]='\e[34m'
[magenta]='\e[35m'
[cyan]='\e[36m'
[gray]='\e[90m'
# LIGHT COLOURS
[lgray]='\e[37m'
[lred]='\e[91m'
[lgreen]='\e[92m'
[lyellow]='\e[93m'
[lblue]='\e[94m'
[lmagenta]='\e[95m'
[lcyan]='\e[96m'
[white]='\e[97m'
[default]='\e[0m' )
我还在另一个文件中有一个脚本,用于将输出集中在终端上,诚然,我从 GitHub:
上的某人的指南中借用了该脚本#!/usr/bin/env bash
# original script by TrinityCoder
# USAGE: printcen "center text" "filler text"
function printcen {
[[ $# == 0 ]] && return 1
declare -i TERM_COLS="$(tput cols)"
declare -i str_len="${#1}"
[[ $str_len -ge $TERM_COLS ]] && {
echo "";
return 0;
}
declare -i filler_len="$(( (TERM_COLS - str_len) / 2 ))"
[[ $# -ge 2 ]] && ch="${2:0:1}" || ch =" "
filler=""
for (( i = 0; i < filler_len; i++ )); do
filler="${filler}${ch}"
done
printf "%s%s%s" "$filler" "" "$filler"
[[ $(( (TERM_COLS - str_len) % 2 )) -ne 0 ]] && printf "%s" "$ch"
printf "\n"
return 0
}
最后,我找到了导致问题的线路本身。我只用这一行试过,所以这里是:
#!/usr/bin/env bash
source ~/.scripts/bagcolors
source ~/.scripts/printcen
printcen " ${fcolors[cyan]} ----========================---- ${fcolors[default]}" " "
当我 运行 文件时,printcen
函数似乎只是准确地打印颜色代码,包括转义序列,就好像它只是一个常规字符串一样。到目前为止,我已经尝试在颜色代码和文本本身之间放置空格,但这似乎没有任何改变。
如有任何帮助,我们将不胜感激。
您的方法存在的问题是您会将 不可见 个字符计为字符串的一部分。
执行此操作(在按照@gniourf_gniourf 指示修复转义序列后)
l=$(printcen '----========================----')
printf '%s%s%s\n' "${fcolors[cyan]}" "$l" "${fcolors[default]}"
第二个问题是您通过 "%s"
转换说明符将 ANSI 转义符放入 printcen
中的 printf
而不是将它们作为格式字符串的一部分。您有两个选择:
printf "%s%s" "$filler" "$filler"
(以上为首选方式)
或者,只需使用命令替换来扩展转义:
printf "%s%s%s" "$filler" $(printf "") "$filler"
(需要一个额外的 subshell)
任何一种方法都应该有效。虽然一开始就使用 ANSI 转义符是值得的,但并不能真正保证它们在 VT 终端仿真之外工作。因此,您使用它们的脚本将不可移植。 (但它们很适合装饰使用)