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"

(需要一个额外的 subshel​​l)

任何一种方法都应该有效。虽然一开始就使用 ANSI 转义符是值得的,但并不能真正保证它们在 VT 终端仿真之外工作。因此,您使用它们的脚本将不可移植。 (但它们很适合装饰使用)