How to justify and center text in bash?

6

2

Newbie here. I'm looking for bash script to center and justify text. My script only works with one line of text. How would you improve it?

#!/bin/bash
COLS=$(tput cols)
while true; do
    clear
    echo -n "Type text "
    read text
    echo
    echo "Menu"
    echo "1) Right justify  "
    echo "2) Center "
    echo "3) Exit "
    echo
    echo -n "Choose [1-3]: "
    read opt
    echo
    case $opt in
        1) printf "%*s\n" $COLS "$text"
           break
        ;;
        2) printf "%*s\n" $[$COLS/2] "$text"
           break
        ;;      
        3) break
        ;;
        *)
        echo "Error. Press [1-3]"
        break
        ;;
    esac
done

Edward

Posted 2014-10-11T14:09:09.920

Reputation: 61

Answers

6

As you have discovered, $COLUMNS is useful only in an interactive -i shell, so we use columns="$(tput cols)" instead.

The only issue I have is with the line below. It does not center text.
printf "%*s\n" $[$COLS/2] "$text"

Expanding on your work, here is a function to display centered text (from from a file). To call it within your script, use display_center "file.txt"

display_center(){
    columns="$(tput cols)"
    while IFS= read -r line; do
        printf "%*s\n" $(( (${#line} + columns) / 2)) "$line"
    done < "$1"
}

Note the use of ${#line} (akin to wc -m) to count the number of characters in the line. As long as you only need to display plain text without colors/formatting, then this should work fine.

Here is a function to display right-justified text (from a file) using your same implementation of printf.

display_right(){
    columns="$(tput cols)"
    while IFS= read -r line; do
        printf "%*s\n" $columns "$line"
    done < "$1"
}

You can also do similar things with tput and echo, but the example below is not so robust (i.e. will fail with long strings).

row=0
col=$(( ($(tput cols) - ${#text}) / 2))
tput clear
tput cup $row $col
echo "$text"

Also, you may want to consider using dialog or select to generate your menu. It would make your script significantly cleaner.
http://bash.cyberciti.biz/guide/Select_loop
https://serverfault.com/questions/144939/multi-select-menu-in-bash-script

Six

Posted 2014-10-11T14:09:09.920

Reputation: 318

3

#!/usr/bin/awk -f
{
  z = 92 - length
  y = int(z / 2)
  x = z - y
  printf "%*s%s%*s\n", x, "", $0, y, ""
}

Input

hello world
alpha bravo charlie delta

Output

                                         hello world
                                  alpha bravo charlie delta

Steven Penny

Posted 2014-10-11T14:09:09.920

Reputation: 7 294

3awk '{ z = '$(tput cols)' - length; y = int(z / 2); x = z - y; printf "%*s%s%*s\n", x, "", $0, y, ""; }' – galva – 2016-06-08T23:20:34.203

1

Without destroying line contents?

This solution will put text in the center of the line in which the cursor is currently on, without printing spaces around its borders. Its useful if you want to center text without destroying what is currently printed on the line.

Notice: Your shell must support ANSI escape sequences for his example to work.

#!/bin/bash
print_center(){
    local x
    local y
    text="$*"
    x=$(( ($(tput cols) - ${#text}) / 2))
    echo -ne "\E[6n";read -sdR y; y=$(echo -ne "${y#*[}" | cut -d';' -f1)
    echo -ne "\033[${y};${x}f$*"
}

# main()

# clear the screen, put the cursor at line 10, and set the text color
# to light blue.
echo -ne "\\033[2J\033[10;1f\e[94m"

# do it!
print_center 'A big blue title!'

The cursor will be left at the end of "title!" in this example. Use another ANSI sequence to relocate the cursor as you see fit.


Pros

  • Works over SSH
  • Can resize device buffer without centering issues (dynamic)
  • Does not destroy line contents
  • ASCII game / animation friendly.

Cons

  • Will not work if your terminal does not support ANSI escape sequences
  • Not intended for rolling log output.
  • Depends on bash

Robert Smith

Posted 2014-10-11T14:09:09.920

Reputation: 51

0

I was also struggling for aligning texts in my bash script so I found solution it is:

# echo -e "\t Hello World!"

Charanjit Cheema

Posted 2014-10-11T14:09:09.920

Reputation: 1