2

I am writing a script to display a menu at the center of the screen for the users to select the options using printf command in bash script.

I am finding the middle column of the screen, and start printing the messages from the middle column. Hence, the output will be displayed at the center.

Below is the code snippet

#!/bin/bash

INSTALLATION_HEADER=" Installater Options "

COLS=$(tput cols)

print_header ()
{
        local equal=()
        local title="$1"
        local mid=$(((${#title}+$COLS)/2))
        for (( i=0;  $i < ${#title} ; i=$(($i+1)) ))
        do
                local hypen+="-"
        done
        printf "%*s\n" $mid "$title"
        printf "%*s\n" $mid "$hypen"
        echo ""
        echo ""
}

print_install_options ()
{
        local title=${1}
        local mid=$(((${#title}+$COLS)/2))
        for (( i=0;  $i < ${#title} ; i=$(($i+1)) ))
        do
                local hypen+="-"
        done

        printf "%*s\n" $mid "$hypen"
        for i in "${install_options[@]}" ;
        do
                printf "%*s\n" $mid "$i"
        done
        printf "%*s\n" $mid "$hypen"
}

install_options=("1. Install" "2. Uninstall")
print_header "$INSTALLATION_HEADER"
print_install_options "$INSTALLATION_HEADER" 

When I execute the above code, the output produced is

 Installater Options
---------------------


---------------------
           1. Install
         2. Uninstall
---------------------

The expected output should be

 Installater Options
---------------------


---------------------
1. Install
2. Uninstall
---------------------

"1. Ïnstall" and "2. Uninstall" are not printing at the middle of the screen. Please help me in resolving it.

Thanks in Advance.

Updated Script:

Thanks to all for anwering my question.

Below is the script which gives the required output.

#!/bin/bash

INSTALLATION_HEADER=" Installater Options "

COLS=$(tput cols)

print_header ()
{
        local equal=()
        local title="$1"
        local mid=$(((${#title}+$COLS)/2))
        for (( i=0;  $i < ${#title} ; i=$(($i+1)) ))
        do
                local hypen+="-"
        done
        printf "%*s\n" $mid "$title"
        printf "%*s\n" $mid "$hypen"
        echo ""
        echo ""
}

print_install_options ()
{
        local title=${1}
        local length=$(((${#title}+$COLS)))
        local mid=$(((${#title}+$COLS)/2))
        for (( i=0;  $i < ${#title} ; i=$(($i+1)) ))
        do
                local hypen+="-"
        done

        printf "%*s\n" $mid "$hypen"
        for i in "${install_options[@]}" ;
        do
                printf "%*s%s" $((${mid}-${#title})) "" "|"
                printf "%s" "  $i  "
                printf "%*s\n" $((${#title}-${#i}-5)) "|"
        done
        printf "%*s\n" $mid "$hypen"
}

install_options=("1. Install" "2. Uninstall")
print_header "$INSTALLATION_HEADER"
print_install_options "$INSTALLATION_HEADER"

Output:

 Installater Options
---------------------


---------------------
|  1. Install       |
|  2. Uninstall     |
---------------------
3
  • Show expected output Commented Nov 13, 2014 at 13:31
  • @Jidder, Added the expected output. Thank you. Commented Nov 13, 2014 at 13:35
  • @sach I have added an answer where I address, in a note, the problem you might have referencing $COLUMNS inside a script. Resumé: $COLUMNS works if you source the script. Commented Nov 13, 2014 at 14:21

3 Answers 3

3

Change line 34 to

printf "%-*s%s\n" $((${mid}-${#title})) " " "$i"

Result:

                                 Installater Options 
                                ---------------------


                                ---------------------
                                1. Install
                                2. Uninstall
                                ---------------------
Sign up to request clarification or add additional context in comments.

3 Comments

It works. Could you please explain the printf used here.
@sach $((${mid}-${#title})) is arithmetic operation which result is $mid minus length of title. So we printf two string (%s): first one is just bare space " " aligned to the left and repeated mid minus #title times. The second string is $i.
Thanks rooom, I have updated my script in the question, please have a look. Any changes plz suggest.
1

Instead of this:

            printf "%*s\n" $mid "$i"

You need this:

            printf "%-*s\n" $mid "$i"

The - means left-align.

3 Comments

I am trying to print the statement which should start at the mid ( which is the center of the screen) value. Here left alignment does not work.
@sach the middle of the screen or the middle of the dashed lines ?
@Jidder, Its middle of the screen.
1

The question is about printing in the centre of a screen, even if the examples refer to a left aligned string (see John's answer for that...) so I will give the answer for centering a string even if it is of tangential interest for the OP

centre () {
    nc=`tput cols`; l=${#1}
    printf "%$(( (nc-l)/2 ))s%s\n" " " "$1"
    }

Comment for the OP

In your code you reference $COLUMNS, look at this:

% cat aaaa
echo pippo $COLUMNS
tput cols
% source aaaa
pippo 117
117
% sh aaaa
pippo
117
% 

and use tput to find the number of columns

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.