Home > Mobile >  Is there a way to display a multiple of x number of characters in an array?
Is there a way to display a multiple of x number of characters in an array?

Time:06-01

I have an array with 252 times this character: █

I want to display the whole array on the screen so that when I resize the terminal window it always displays a multiple of 3 █ on each line. For example, by making the terminal window smaller, only 50 characters fit on each line, so I want to display 48, 48, 48, 48, 48, 48, 48 and 12 on each respective line so that there are multiples of 3 on every line.

To do this I am trying to use $(tput cols) to calculate the width of the screen and subtract 7 units to have a margin to the right of the terminal. Also, my tam_total variable contains the number of █ in the array, in this case it contains a 252. The variable r contains the value of the line being written - 1.

Finally, in the last row of the terminal I want to add the value of $tam_total, which works perfectly for me.

tamanopantalla=$(tput cols)
let "tam_pantalla_usable=tamanopantalla-7"

for ((r=0;r<${#array[@]};r  )){
    if [[ $r -eq 0 ]]
    then 
        if [[ $tam_total -le $tam_pantalla_usable ]] 
        then
            echo -e "${array[$r]}""T=$tam_total"
        else 
            echo -e "${array[$r]}"
        fi
    else
        let "ult_linea=r 1"
        if [[ $tam_total -ge $tam_pantalla_usable ]] && [[ $ult_linea = ${#array[@]} ]]
        then
            echo -e "${array[$r]}""T=$tam_total"
        else 
            echo -e "${array[$r]}"
        fi
    fi
}

What I would like to know is if there is an easy way to show multiples of 3 █ in all my lines.

CodePudding user response:

A quick example loop, just to manage the consumption of the base string -
Given

$: scr=50
$: tmp=$(perl -e 'print "x"x252') # x's easier to verify visually
$: printf $tmp|wc -c
252

I ran this loop, with the following results:

while ((${#tmp}))                    # while the var has length
do max=$(( scr-(scr%3) ))            # scr-(scr%3) sets to highest multiple of 3
   ((max > ${#tmp})) && max=${#tmp}  # when remaining shorter, use that
   echo "$max: ${tmp:0:$max}"        # show length and the string 
   tmp=${tmp:$max}                   # chop used part off the front
done
48: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
48: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
48: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
48: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
48: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
12: xxxxxxxxxxxx

CodePudding user response:

Try this Shellcheck-clean code:

#! /bin/bash -p

for i in {1..252}; do array =( '#' ); done
tam_total=${#array[*]}

tamanopantalla=$(tput cols)
tam_pantalla_usable=$(( (tamanopantalla-7) / 3 * 3 ))

for ((i=0; i<tam_total; i =tam_pantalla_usable)); do
    printf '%s' "${array[@]:i:tam_pantalla_usable}"
    printf '\n'
done

printf 'T=%d\n' "$tam_total"
  • I've initialized array with # characters for convenience. You'll need to change this.
  • The (tamanopantalla-7) / 3 * 3 arithmetic expression first subtracts 7 from the width to allow for the margin, (integer) divides by 3 to get the largest integer less than or equal to one third the adjusted width, and then multiplies by 3 to get the largest multiple of 3 less than or equal to the adjusted width.
  • See How to slice an array in Bash for an explanation of "${array[@]:i:tam_pantalla_usable}.
  • See printf returns multiple copies for an explanation of why printf '%s' ... prints more than one string.
  • Related