12

I'm working with select and case in bash. I currently have nine options, which makes a nice, tidy, 3x3 grid of options, but it displays like so:

    1) show all elements  4) write to file      7) clear elements
    2) add elements       5) generate lines     8) choose file
    3) load file          6) clear file         9) exit

I'd prefer if it displayed in rows before columns:

1) show all elements  2) add elements    3) load file
4) write to file      5) generate lines  6) clear file  
7) clear elements     8) choose file     9) exit

Is there any way to accomplish this? Preferably something easy to set and unset within a script, like a shell option. If it matters, the options are stored in an array, and referenced in the case blocks by the index of the array.

OPTIONS=("show all elements" "add elements" "load file" "write to file" "generate lines" "clear file" "clear elements" "choose file" "exit")

...

select opt in "${OPTIONS[@]}"
do
case $opt in
    "${OPTIONS[0]}")

...

    "${OPTIONS[8]}")
        echo "Bye bye!"
        exit 0
        break
        ;;

    *)
        echo "Please enter a valid option."
esac
done

2 Answers 2

8

Create your own "select":

#!/bin/bash

options=("show all elements" "add elements" "load file" "write to file" "generate lines" "clear file" "clear elements" "choose file" "exit")
width=25
cols=3

for ((i=0;i<${#options[@]};i++)); do 
  string="$(($i+1))) ${options[$i]}"
  printf "%s" "$string"
  printf "%$(($width-${#string}))s" " "
  [[ $(((i+1)%$cols)) -eq 0 ]] && echo
done

while true; do
  echo
  read -p '#? ' opt
  case $opt in
    1)
      echo "${options[$opt-1]}"
      ;;

    2)
      echo "${options[$opt-1]}"
      ;;

    9)
      echo "Bye bye!"
      break
      ;;
  esac
done

Output:

1) show all elements     2) add elements          3) load file             
4) write to file         5) generate lines        6) clear file            
7) clear elements        8) choose file           9) exit                  
#? 
0
1

You can set COLUMNS, see bash manpage.

COLUMNS
    Used  by the select compound command to determine the terminal width when 
    printing selection lists. Automatically set if the checkwinsize option is 
    enabled or in an interactive shell upon receipt of a SIGWINCH.
#!/bin/bash

COLUMNS=X

select item in {a..f}; do
    # ...
done

# COLUMNS=20
# 1) a  3) c  5) e
# 2) b  4) d  6) f 

# COLUMNS=15
# 1) a  4) d
# 2) b  5) e
# 3) c  6) f
1
  • 1
    this doesn't show rows first like what the OP wants
    – phuclv
    Commented Sep 25, 2022 at 2:36

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .