繁体   English   中英

无论输出 bash printf 将文本保持在原位

[英]Keep text in place regardless output bash printf

当数字变大时会发生这种情况......刚开始这个烂摊子。 文本被更大的输出推来推去……我该如何收容这些混乱?

       Accounts......: 5      Mail..........: 7
       Banned........: 0      Pets..........: 1
       Online........: 0      Tickets.......: 0
       Guilds........: 1      Corpses.......: 0      PvP.......: 0
       Members.......: 1      Characters....: 10      Gifts.....: 4   <-----HOWTO Reserve/Preserve spaces ?? ??

应该是这样的:

       Accounts......: 5      Mail..........: 7
       Banned........: 0      Pets..........: 1
       Online........: 0      Tickets.......: 0
       Guilds........: 1      Corpses.......: 0      PvP.......: 0
       Members.......: 1      Characters....: 10     Gifts.....: 4

现在这个烂摊子看起来像这样:


ch_count=$(mysql --defaults-extra-file="$sql_mycnf" -N --execute="SELECT count(*) FROM $db_characters.characters;"); &> /dev/null


cm_char="\033[0mCharacters\e[0;32m....:\033[0m $ch_count\e[31m"

line="      "

           $cm_acco$line$cm_mail
           $cm_bann$line$cm_pets
           $cm_onli$line$cm_tick
           $cm_guil$line$cm_corp$line$cm_pvps
           $cm_memb$line$cm_char$line$cm_gifts

在另一台服务器上有相同的输出,但因为它们较小,所以看起来不错:

           Accounts......: 4      Mail..........: 0
           Banned........: 0      Pets..........: 0
           Online........: 0      Tickets.......: 0
           Guilds........: 0      Corpses.......: 0      PvP.......: 0
           Members.......: 0      Characters....: 2      Gifts.....: 0

编辑此行以使其工作? 这是正确的起点吗?

cm_char="\033[0mCharacters\e[0;32m....:\033[0m $ch_count\e[31m"

杀我。

创建 2 个函数来格式化字段并使用它们:

dot_field() {
   # todo Change implementation when field can be 2 words with a space in between
   printf "%-14.14s:" "$1" | tr ' ' '.'
}

space_number() {
   printf "%-7.7s" "$1"
}

printline() {
   # Todo: add logic when only 4 parameters are given
   echo "       $(dot_field $1) $(space_number $2)$(dot_field $3) $(space_number $4)$(dot_field $5) $(space_number $6)"
}

printline "Guilds" 1 "Corpses" 0 "PvP" 0
printline "Members" 1 "Characters" 10 "Gifts" 4
printline "LongFieldName" 1 "High" 999999 "X" 2

编辑:添加颜色。

您不想让您的代码充满颜色的转义码。 这取决于您希望如何构建颜色代码的完整上下文,我为问题的有限上下文举了一个例子。 它应该让您了解如何为自己制作这样的东西。

init_colors() {
    reset=$(tput sgr0)
    bold=$(tput bold)
    black=$(tput setaf 0)
    red=$(tput setaf 1)
    green=$(tput setaf 2)
    yellow=$(tput setaf 3)
    blue=$(tput setaf 4)
    magenta=$(tput setaf 5)
    cyan=$(tput setaf 6)
    white=$(tput setaf 7)
    user_color=$bold
}

# colorstring reads from stdin and uses parameter 1 as an escape sequence
# with more parameters the first is used as a color, the other as the string to be modified
# It will set colors until the last space sequence
colorstring() {
   case $# in
   0) # invalid
      echo "colorstring called without parameters"
   ;;
   1)
      sed -r "s/^.*[^ ]/$1&${reset}/"
      ;;
   *)
      color="$1"
      shift
      sed -r "s/^.*[^ ]/${color}&${reset}/" <<< "$@"
   ;;
   esac

}

dot_field() {
   # todo Change implementation when field can be 2 words with a space in between
   printf "%-14.14s" "$1" | colorstring ${cyan} | tr ' ' '.'
   # The : must be printed in a second statement when you don't want cyan dots.
   printf ':'
}

space_number() {
   printf "%-7.7s" "$1" | colorstring ${red}
}

printline() {
   echo "       $(dot_field $1) $(space_number $2)$(dot_field $3) $(space_number $4)$(dot_field $5) $(space_number $6)"
}

# init the color variables
init_colors
# Next echo not needed, just testing the new colorstring function
echo "$(colorstring ${blue} blue string) $(colorstring ${red} red car) $(colorstring ${white} white snow) $(colorstring ${yellow} yellow marker) $(colorstring ${cyan} cyan) "
printline "Guilds" 1 "Corpses" 0 "PvP" 0
printline "Members" 1 "Characters" 10 "Gifts" 4
printline "LongFieldName" 1 "High" 999999 "X" 2

正如您可能已经知道的那样,有一些特殊的系统序列可以控制到终端的输出。 例如,这会将文本变为红色 '\e[31m' 并且这将在特定列\行中打印文本 '\e[${LINE};${COLUMN}H'。 所以我们将使用它。 首先,我将使用“名称值”对创建这个“数据”数组来模拟您的情况。

data=(
    "Accounts   5"
    "Banned     10"
    "Online     40"
    "Guilds     4"
    "Members    1"
    "Mail       71"
    "Pets       43"
    "Tickets    0"
    "Corpses    101"
    "Characters 10"
    "PvP        0"
    "Gifts      4"
)

我在处理文本输出时使用了这个,所以让我们用它来

#--------------------------------------------------------------------+
#Color picker, usage: printf ${BLD}${CUR}${RED}${BBLU}"Hello!)"${DEF}|
#-------------------------+--------------------------------+---------+
#       Text color        |       Background color         |         |
#-----------+-------------+--------------+-----------------+         |
# Base color|Lighter shade|  Base color  | Lighter shade   |         |
#-----------+-------------+--------------+-----------------+         |
BLK='\e[30m'; blk='\e[90m'; BBLK='\e[40m'; bblk='\e[100m' #| Black   |
RED='\e[31m'; red='\e[91m'; BRED='\e[41m'; bred='\e[101m' #| Red     |
GRN='\e[32m'; grn='\e[92m'; BGRN='\e[42m'; bgrn='\e[102m' #| Green   |
YLW='\e[33m'; ylw='\e[93m'; BYLW='\e[43m'; bylw='\e[103m' #| Yellow  |
BLU='\e[34m'; blu='\e[94m'; BBLU='\e[44m'; bblu='\e[104m' #| Blue    |
MGN='\e[35m'; mgn='\e[95m'; BMGN='\e[45m'; bmgn='\e[105m' #| Magenta |
CYN='\e[36m'; cyn='\e[96m'; BCYN='\e[46m'; bcyn='\e[106m' #| Cyan    |
WHT='\e[37m'; wht='\e[97m'; BWHT='\e[47m'; bwht='\e[107m' #| White   |
#----------------------------------------------------------+---------+
# Effects                                                            |
#--------------------------------------------------------------------+
DEF='\e[0m'   #Default color and effects                             |
BLD='\e[1m'   #Bold\brighter                                         |
DIM='\e[2m'   #Dim\darker                                            |
CUR='\e[3m'   #Italic font                                           |
UND='\e[4m'   #Underline                                             |
INV='\e[7m'   #Inverted                                              |
COF='\e[?25l' #Cursor Off                                            |
CON='\e[?25h' #Cursor On                                             |
#--------------------------------------------------------------------+
# Text positioning, usage: XY 10 10 "Hello World!"                   |
XY   () { printf "\e[${2};${1}H${3}"; } #                            |
#--------------------------------------------------------------------+
# Print line, usage: line - 10 | line -= 20 | line "Hello World!" 20 |
line () { printf -v LINE "%$2s"; printf -- "${LINE// /$1}"; } #      |
# Create sequence like {0..X}                                        |
cnt () { printf -v _N %$1s; _N=(${_N// / 1}); printf "${!_N[*]}"; } #|
#--------------------------------------------------------------------+

所有基本颜色都设置为 vars 以便轻松插入文本和一些有用的函数,如 XY,我将使用它在 serrtain 位置打印文本。

让我们设置一些变量

space_betwen=7  # space betwen columns
X=$space_betwen # starting X(column) position
Y=10            # starting Y(line) position

dot_string='...............: ' # dot string to simulate your output
dot_length=${#dot_string}      # this will calculate the length of the dot string

好的,我们准备好了,但首先让我们清除终端屏幕上的所有文本

clear

现在我们可以遍历数据并打印 3 列 4 行的文本

for item in "${data[@]}"; {
    ((counter++)) # lets count items to know when start next column
    read name value <<< $item # get naame and value from current item
    XY $X $Y "$dot_string$RED$value$DEF" # print dot string and red value
    XY $X $Y "$YLW$name$DEF" # name will be printed ower dots in yelow color
    ((Y++)) # go to next line by increasing Y value
    # chek if we print 4 lines than set Y to start poosition and inc X to space_betwen+dot_length
    ((counter%4)) || { Y=10; ((X+=space_betwen+dot_length)); }
}

最终的脚本会是这样的

    #!/bin/bash

    data=(
        "Accounts   5"
        "Banned     10"
        "Online     40"
        "Guilds     4"
        "Members    1"
        "Mail       71"
        "Pets       43"
        "Tickets    0"
        "Corpses    101"
        "Characters 10"
        "PvP        0"
        "Gifts      4"
    )

    . ~/SCR/color   # include color table
    space_betwen=7  # space betwen columns
    X=$space_betwen # starting X(column) position
    Y=10            # starting Y(line) position

    dot_string='...............: ' # dot string to simulate your output
    dot_length=${#dot_string}      # this will calculate the length of the dot string

clear

for item in "${data[@]}"; {
    ((counter++)) # lets count items to know when start next column
    read name value <<< $item # get naame and value from current item
    XY $X $Y "$dot_string$RED$value$DEF" # print dot string and red value
    XY $X $Y "$YLW$name$DEF" # name will be printed ower dots in yelow color
    ((Y++)) # go to next line by increasing Y value
    # chek if we print 4 lines than set Y to start poosition and inc X to space_betwen+dot_length
    ((counter%4)) || { Y=10; ((X+=space_betwen+dot_length)); }
}
XY 1 20 "$DEF" # one more time to move cursor down in the end

输出将是这样的输出示例

暂无
暂无

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

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