Enum datatype apparently not available in bash

Having bash, we created simple scripts to access the array element using 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 the above scripts, I need to declare the correct index variable to retrieve a valid message from the list of arrays, but it is probably not convenient for me to declare each variable and give an index to them. It’s nice if a variable automatically gets a value like in C for ENUMa data type

in C it's possible with

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

is there an alternative for ENUMin bash?

I found a lot, but did not succeed, and then tried some sort of trick to achieve this.

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

, , , . 5-10 , .

, ?

+4
4

... , ,

#!/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
+3

, , . , :

 state=IDLE
 ...
 while [ $state = IDLE ]
 do
   ...
   if condition
   then
     state=BUSY
   fi
   ...
   if condition2
   then
     state=ERROR
   fi
   ...
 done
 if [ $state = ERROR ]
 then
   ...
 fi

, , :

  • ( )
  • ( , )
  • / ( )
+1

:

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

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

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

:

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

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

, .

Another solution is to assign values ​​to an associative array to create an enum set with the variable name as a prefix. This allows you to perform an enumeration self-analysis by looking at all the 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 (loop):

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 do not have a specific order, but can always be sorted later.

+1
source

You can combine some lines:

for i in E_OK E_CANCEL E_ERROR E_CONFIRM E_SAVE E_EXIT; do declare -r ${i}=$((x++)); done

Output:

for i in ${!E_@}; do echo $i=${!i}; done

E_CANCEL=1
E_CONFIRM=3
E_ERROR=2
E_EXIT=5
E_OK=0
E_SAVE=4
+1
source

All Articles