-
Notifications
You must be signed in to change notification settings - Fork 56
Bash sample code: Create an interactive menu
Display an interactive menu in your Bash scripts like 42FileChecker does.
We are going to create a 3 items menu so that the user will be asked to type a number between 1 and 3. The idea is to read the sandard input from the keyboard with the function read
, to check if an action has been defined in an array called MY_ACTIONS
and finally to execute the action with the command eval
:
function do_libft
{
echo "-> You selected LIBFT"
display_menu
}
function do_libftasm
{
echo "-> You selected LIBFTASM"
display_menu
}
function do_exit
{
echo "-> Exit the script"
exit
}
# Function that displays the menu
function display_menu
{
# Declare an array containing the actions to do
local -a MY_ACTIONS
MY_ACTIONS[1]="do_libft"
MY_ACTIONS[2]="do_libftasm"
MY_ACTIONS[3]="do_exit"
# Display items
local -i I=1
echo "#########################"
while [ $I -le ${#MY_ACTIONS[@]} ]
do
echo "$I) ${MY_ACTIONS[$I]}"
(( I += 1 ))
done
# Read keyboard silently, one character at a time,
# and save the value in $SELECTION
local SELECTION
read -s -n1 SELECTION
# Convert the ascii value of $SELECTION into a numeric index
local ORD_VALUE=$(LC_CTYPE=C printf '%d' "'$SELECTION")
(( ORD_VALUE -= 48 ))
# Check if the index is valid
if [ $ORD_VALUE -gt 0 -a $ORD_VALUE -le ${#MY_ACTIONS[@]} ]
then
# If yes, evaluate the action and exit the function
eval ${MY_ACTIONS[${ORD_VALUE}]}
return
fi
# If not, call display_menu one more time
echo "-> INVALID SELECTION"
display_menu
}
# Call the menu
display_menu
function get_ord
{
LC_CTYPE=C printf '%d' "'$1"
}
get_ord "1" # Print ASCII value of "1": 49
get_ord "A" # Print ASCII value of "A": 65
declare -i VALUE=$(get_ord "1") # Save the result in a variable $VALUE
(( VALUE -= 48 )) # Do an arithmetic operation
echo $VALUE # Print the numeric value of "1": 1
In the current example of menu, we set an array MY_ARRAY
containing 3 indexes from 1 to 3. The arithmetic comparisons we need to do are: "greater than" 0 (-gt) and "less or equal than" 3 (-le). 3 is also the count number of items in the array, then we use the special symbol #
before the name of the array to get its length and the special parameter [@]
to expand all items of the array. -a
is an "AND" operator that permits to join our two comparisons.
# C equivalent: if (ord_value > 0 and ord_value <= length)
if [ $ORD_VALUE -gt 0 -a $ORD_VALUE -le ${#MY_ACTIONS[@]} ]
then
# ...
fi
We also could have use the "zero" test (-z) that returns success when a string is empty:
# Invert the test by using the symbol '!'
if [ ! -z ${MY_ACTIONS[$ORD_VALUE]} ]
then
# This test causes an error when $ORD_VALUE is a negative number
# Array indexes can only be positive or zero
fi
eval
is a builtin command that interprets a string or a list of arguments as a command line:
# Convert a string into a command line
declare ACTION="echo '42FileChecker' | cat -e"
eval $ACTION
# Convert a list of arguments into a command line
eval "echo" "42FileChecker" "|" "cat -e"
Introduction:
- What is Bash
- What is a bash script
- What is 42FileChecker
- Contributing to 42FileChecker
Bash syntax:
Bash tools:
- Builtin commands
- Awk
- Cat
- Grep
- Sed
Bash sample codes:
- Script auto-update (git tool)
- Create an interactive menu
- Animated spinner with a time out
- Static var test
- Check the basic rules of a makefile
- Forbidden functions test
- Memory leak test script
- Create a speed test