Держите текст на месте независимо от вывода bash printf - PullRequest
2 голосов
/ 22 января 2020

Это происходит, когда числа становятся больше ... Только началось с этого беспорядка. Текст перемещается большими выходными данными ... как мне содержать этот беспорядок?

       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 ]

3 голосов
/ 22 января 2020

Создайте 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

РЕДАКТИРОВАТЬ: Добавление цветов.

Вы не хотите, чтобы ваш код был полон escape-кодов для цветов. От полного контекста зависит, как вы хотели бы структурировать свои цветовые коды, я приведу пример для ограниченного контекста вопроса. Это должно дать вам представление о том, как вы можете сделать что-то подобное для себя.

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
2 голосов
/ 23 января 2020

Как вы, возможно, уже знаете, существуют некоторые особые системные сиквены, которые контролируют вывод на терминал. Это, например, сделает текст красным «\ e [31m», и это напечатает текст в определенном столбце \ line '\ 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[*]}"; } #|
#--------------------------------------------------------------------+

Все основные цвета c установлены как переменные для легкой вставки в текст, а некоторые полезные функции, такие как 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

Хорошо, мы готовы к go, но сначала давайте очистим весь текст с экрана терминала

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

И вывод будет таким: output example

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...