简体   繁体   English

printf 转义码未在 Bash 脚本中格式化

[英]printf escape code not formatting in Bash script

I've recently started playing around with Bash, mostly using it to customize my .profile , and I've ran into an issue with the printf command.我最近开始玩 Bash,主要是用它来自定义我的.profile ,我遇到了printf命令的问题。

In my scripts folder, I have an associative array set up for easy use of ANSI colour codes:在我的脚本文件夹中,我设置了一个关联数组,以便于使用 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' )

I also, in yet another file, have a script to center output on the terminal, which, admittedly, I borrowed from someone's guide on GitHub:在另一个文件中,我还有一个脚本可以在终端上将 output 居中,诚然,我从某人的 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 "$1";
                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" "$1" "$filler"
        [[ $(( (TERM_COLS - str_len) % 2 )) -ne 0 ]] && printf "%s" "$ch"
        printf "\n"

        return 0
}

And, finally, I have the line itself that's causing the issue.最后,我有导致问题的线路本身。 I've only tried this with this one line, so here it is:我只用这一行试过这个,所以这里是:

#!/usr/bin/env bash

source ~/.scripts/bagcolors
source ~/.scripts/printcen

printcen " ${fcolors[cyan]} ----========================---- ${fcolors[default]}" " "

When I run the file, the printcen function seems to just print the colour codes exactly, including the escape sequence, as if it were just a regular string.当我运行该文件时, printcen function 似乎只是准确地打印颜色代码,包括转义序列,就好像它只是一个常规字符串一样。 So far, I've tried putting spaces between the colour codes and the text itself, but that didn't seem to change anything.到目前为止,我已经尝试在颜色代码和文本本身之间放置空格,但这似乎并没有改变任何东西。

Any help with this would be appreciated.对此的任何帮助将不胜感激。

The problem with your approach is that you'll be counting invisible chars as part of the string.您的方法的问题是您会将不可见的字符计为字符串的一部分。

Do this (after you fix the escape sequences as indicated by @gniourf_gniourf)执行此操作(在您修复 @gniourf_gniourf 指示的转义序列之后)

l=$(printcen '----========================----')
printf '%s%s%s\n' "${fcolors[cyan]}" "$l" "${fcolors[default]}"

The second issue is you are putting the ANSI escapes through the "%s" conversion specifier to printf in printcen rather than making them part of the format string.第二个问题是您通过"%s"转换说明符将 ANSI 转义符printf中的printcen ,而不是使它们成为格式字符串的一部分。 You have two options:你有两个选择:

printf "%s$1%s" "$filler" "$filler"

(the above is the preferred way) (以上是首选方式)

Or, just use command substitution to expand the escapes:或者,只需使用命令替换来扩展转义:

printf "%s%s%s" "$filler" $(printf "$1") "$filler"

(costs an additional subshell) (需要额外的子外壳)

Either way should work.无论哪种方式都应该有效。 Though it is worth the normal caution about using ANSI escapes to begin with, there isn't really a guarantee they work outside the VT terminal emulation.尽管一开始就使用 ANSI 转义符值得谨慎,但并不能保证它们在 VT 终端仿真之外也能正常工作。 So your script using them won't be portable.因此,您使用它们的脚本将不可移植。 (but they are nice for decorative use) (但它们很适合装饰用途)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM