Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

enum data type seems not available in bash

Tags:

linux

bash

enums

Having bash, created simple scripts for accessing array element by it's index.It as follows

#! /bin/bash

OK_INDEX=0
CANCEL_INDEX=1
ERROR_INDEX=2
CONFIRM_INDEX=3
SAVE_INDEX=4
EXIT_INDEX=5
declare -a messageList=("ok" 
                        "cancel" 
                        "error" 
                        "confirm"
                        "save"
                        "exit")

printf "%s \n" ${messageList[$CANCEL_INDEX]}

from above scripts i need to declare proper index variable to retrieve valid message from array list but it likely not handy for me to declare each variable and give index to them.It is nice if variable autometically getting value as like in C for ENUM data type

in C it's possible by like

enum index { OK_INDEX, CANCEL_INDEX, ERROR_INDEX,CONFIRM_INDEX,SAVE_INDEX,EXIT_INDEX};

is there any alternative for ENUM in bash?

I found lot but not succeded then have try some trick to achieve this it is as follows

ENUM=(OK_INDEX CANCEL_INDEX ERROR_INDEX CONFIRM_INDEX SAVE_INDEX EXIT_INDEX)

maxArg=${#ENUM[@]}

for ((i=0; i < $maxArg; i++)); do
    name=${ENUM[i]}
    declare -r ${name}=$i
done

So form above code snippet i successfully created constant but it seems lengthy means just declaring variable i need to write 5-10 lines code which is not fair.

So any one have another solution?

like image 495
Jayesh Bhoi Avatar asked Feb 13 '23 18:02

Jayesh Bhoi


2 Answers

Try the following fragment of code ... I guess that it is what you want

#!/bin/bash
set -u 
DEBUG=1

# This funcion allow to declare enum "types", I guess
enum ()
{
    # skip index ???
    shift
    AA=${@##*\{} # get string strip after { 
    AA=${AA%\}*} # get string strip before }
    AA=${AA//,/} # delete commaa  
    ((DEBUG)) && echo $AA
    local I=0
    for A in $AA ; do
        eval "$A=$I"
        ((I++))
    done
}

### Main program 
# Just declare enum as you need
enum index { OK_INDEX, CANCEL_INDEX, ERROR_INDEX, CONFIRM_INDEX, SAVE_INDEX, EXIT_INDEX };
# Print value of enumerated items
echo $OK_INDEX
echo $CANCEL_INDEX 
echo $ERROR_INDEX  
echo $CONFIRM_INDEX
echo $SAVE_INDEX
echo $EXIT_INDEX

# Use enumerated index in program
I=CONFIRM_INDEX
case $I in  
    OK_INDEX )
        echo "Process here when index is $I"
    ;;
    CANCEL_INDEX )
        echo "Process here when index is $I"
    ;;
    ERROR_INDEX )
        echo "Process here when index is $I"
    ;;
    CONFIRM_INDEX )
        echo "Process here when index is $I"
    ;;  
    SAVE_INDEX )
        echo "Process here when index is $I"
    ;;  
    EXIT_INDEX )
        echo "Process here when index is $I"
    ;;  
esac  

exit 0
like image 155
abadjm Avatar answered Feb 17 '23 02:02

abadjm


My take on this:

function \
   _enum()
{
   ## void
   ## (
   ##    _IN $@ : [ array<string> ] list
   ## )

   local list=("$@")
   local len=${#list[@]}

   for (( i=0; i < $len; i++ )); do
      eval "${list[i]}=$i"
   done
}

Example:

ENUM=(
   OK_INDEX
   CANCEL_INDEX
   ERROR_INDEX
   CONFIRM_INDEX
   SAVE_INDEX
   EXIT_INDEX
) && _enum "${ENUM[@]}"

echo "OK_INDEX = "$OK_INDEX
echo "CANCEL_INDEX = "$CANCEL_INDEX
echo "ERROR_INDEX = "$ERROR_INDEX
echo "CONFIRM_INDEX = "$CONFIRM_INDEX
echo "SAVE_INDEX = "$SAVE_INDEX
echo "EXIT_INDEX = "$EXIT_INDEX

Output

OK_INDEX = 0
CANCEL_INDEX = 1
ERROR_INDEX = 2
CONFIRM_INDEX = 3
SAVE_INDEX = 4
EXIT_INDEX = 5

I find this to be the cleanest and most straightforward approach.

Another solution is to assign values to an associative array to make an enum set with the variable name as the prefix. This allows introspection of the enum by walking through all available values and their associated key names:

function \
   _enum_set()
{
   ## void
   ## (
   ##    _IN  $1 : [ string ] prefix
   ##    _IN ... : [ array<string> ] list
   ## )

   local prefix=$1
   local list=("$@")
   local len=${#list[@]}

   declare -g -A $prefix

   for (( i=0; i < $len; i++ )); do
      # Skip the first argument
      [[ $i = 0 ]] &&
         continue

      eval "$prefix[${list[$i]}]=$(( $i - 1 ))"
   done
}

Example (looping):

ENUM=(
   OK
   CANCEL
   ERROR
   CONFIRM
   SAVE
   EXIT
) && _enum_set ENUM_INDEX "${ENUM[@]}"

echo ""
for i in "${!ENUM_INDEX[@]}"; do
   echo "ENUM_INDEX[$i] = "${ENUM_INDEX[$i]}
done

Output:

ENUM_INDEX[CONFIRM] = 3
ENUM_INDEX[OK] = 0
ENUM_INDEX[EXIT] = 5
ENUM_INDEX[ERROR] = 2
ENUM_INDEX[SAVE] = 4
ENUM_INDEX[CANCEL] = 1

Example (explicit):

ENUM=(
   OK
   CANCEL
   ERROR
   CONFIRM
   SAVE
   EXIT
) && _enum_set ENUM_INDEX "${ENUM[@]}"

echo "ENUM_INDEX[OK] = "${ENUM_INDEX[OK]}
echo "ENUM_INDEX[CANCEL] = "${ENUM_INDEX[CANCEL]}
echo "ENUM_INDEX[ERROR] = "${ENUM_INDEX[ERROR]}
echo "ENUM_INDEX[CONFIRM] = "${ENUM_INDEX[CONFIRM]}
echo "ENUM_INDEX[SAVE] = "${ENUM_INDEX[SAVE]}
echo "ENUM_INDEX[EXIT] = "${ENUM_INDEX[EXIT]}

Output:

ENUM_INDEX[OK] = 0
ENUM_INDEX[CANCEL] = 1
ENUM_INDEX[ERROR] = 2
ENUM_INDEX[CONFIRM] = 3
ENUM_INDEX[SAVE] = 4
ENUM_INDEX[EXIT] = 5

Note that associative arrays have no defined order but can always be sorted at a later point.

like image 31
Zhro Avatar answered Feb 17 '23 03:02

Zhro