[英]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.