5

How can I print $myvar padded so that it is in the center of the terminal, and to either side are = to the edge of the screen?

6

I found two pieces of information here on the stackexchange network that helped me arrive at this working answer:

However the code in this answer is my own.

See the edit history if you want more verbosity; I've edited out all the cruft and "steps along the way."


I think the best way is:

center() {
  termwidth="$(tput cols)"
  padding="$(printf '%0.1s' ={1..500})"
  printf '%*.*s %s %*.*s\n' 0 "$(((termwidth-2-${#1})/2))" "$padding" "$1" 0 "$(((termwidth-1-${#1})/2))" "$padding"
}
center "Something I want to print"

Output on a terminal 80 columns wide:

========================== Something I want to print ===========================

Note that the padding doesn't have to be a single character; in fact the padding variable isn't, it's 500 characters long in the above code. You could use some other form of padding by changing just the padding line:

padding="$(printf '%0.2s' ^v{1..500})"

Results in:

^v^v^v^v^v^v^v^v^v^v^v^v^v Something I want to print ^v^v^v^v^v^v^v^v^v^v^v^v^v^

Another handy use is:

clear && center "This is my header"
0

This proposition seems functional but implies that the terminal supports the terminfo capabilities cols, hpa, ech, cuf, and cud1, c.f. tput (1), terminfo (5), infocmp (1m).

#!/bin/bash

# Function "center_text": center the text with a surrounding border

# first argument: text to center
# second argument: glyph which forms the border
# third argument: width of the padding

center_text()
{
    local terminal_width=$(tput cols)    # query the Terminfo database: number of columns
    local text="${1:?}"                  # text to center
    local glyph="${2:-=}"                # glyph to compose the border
    local padding="${3:-2}"              # spacing around the text

    local border=                        # shape of the border
    local text_width=${#text}

    # the border is as wide as the screen
    for ((i=0; i<terminal_width; i++))
    do
        border+="${glyph}"
    done

    printf "$border"

    # width of the text area (text and spacing)
    local area_width=$(( text_width + (padding * 2) ))

    # horizontal position of the cursor: column numbering starts at 0
    local hpc=$(( (terminal_width - area_width) / 2 ))

    tput hpa $hpc                       # move the cursor to the beginning of the area

    tput ech $area_width                # erase the border inside the area without moving the cursor
    tput cuf $padding                   # move the cursor after the spacing (create padding)

    printf "$text"                      # print the text inside the area

    tput cud1                           # move the cursor on the next line
}

center_text "Something I want to print" "~"
center_text "Something I want to print" "=" 6

The following proposition is robust and extensible and clearer than @Wildcard's solution.

#!/bin/bash

# Function "center_text": center the text with a surrounding border

# first argument: text to center
# second argument: glyph which forms the border
# third argument: width of the padding

center_text()
{

    local terminal_width=$(tput cols)     # query the Terminfo database: number of columns
    local text="${1:?}"                   # text to center
    local glyph="${2:-=}"                 # glyph to compose the border
    local padding="${3:-2}"               # spacing around the text

    local text_width=${#text}             

    local border_width=$(( (terminal_width - (padding * 2) - text_width) / 2 ))

    local border=                         # shape of the border

    # create the border (left side or right side)
    for ((i=0; i<border_width; i++))
    do
        border+="${glyph}"
    done

    # a side of the border may be longer (e.g. the right border)
    if (( ( terminal_width - ( padding * 2 ) - text_width ) % 2 == 0 ))
    then
        # the left and right borders have the same width
        local left_border=$border
        local right_border=$left_border
    else
        # the right border has one more character than the left border
        # the text is aligned leftmost
        local left_border=$border
        local right_border="${border}${glyph}"
    fi

    # space between the text and borders
    local spacing=

    for ((i=0; i<$padding; i++))
    do
        spacing+=" "
    done

    # displays the text in the center of the screen, surrounded by borders.
    printf "${left_border}${spacing}${text}${spacing}${right_border}\n"
}

center_text "Something I want to print" "~"
center_text "Something I want to print" "=" 6

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.