有了bash,用它的索引创建了用于访问数组元素的简单脚本。如下
#! /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]}
从上面的脚本我需要声明正确的索引变量来从数组列表中检索有效的消息但是我可能不方便我声明每个变量并给它们索引。如果变量自动获取值就像在C中一样很好ENUM
数据类型
enum index { OK_INDEX, CANCEL_INDEX, ERROR_INDEX,CONFIRM_INDEX,SAVE_INDEX,EXIT_INDEX};
bash中有ENUM
的替代方法吗?
我发现很多但没有成功然后尝试了一些技巧来实现这一点,如下所示
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行代码,这是不公平的。
那么任何人都有另一种解决方案吗?
答案 0 :(得分:3)
尝试下面的代码片段......我想这就是你想要的
#!/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
答案 1 :(得分:1)
需要枚举时的典型解决方法是使用普通字符串。在这些情况下,我甚至省略了围绕变量评估的其他强制性报价:
state=IDLE
...
while [ $state = IDLE ]
do
...
if condition
then
state=BUSY
fi
...
if condition2
then
state=ERROR
fi
...
done
if [ $state = ERROR ]
then
...
fi
这样,当然,您只具有命名状态的基本功能,而且以下两者通常都没有相关的枚举功能:
答案 2 :(得分: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
我发现这是最干净,最直接的方法。
另一种解决方案是将值分配给关联数组,以将变量名作为前缀的枚举集。通过遍历所有可用值及其关联的键名称,可以进行自省。
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
}
示例(循环):
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
输出:
ENUM_INDEX[CONFIRM] = 3
ENUM_INDEX[OK] = 0
ENUM_INDEX[EXIT] = 5
ENUM_INDEX[ERROR] = 2
ENUM_INDEX[SAVE] = 4
ENUM_INDEX[CANCEL] = 1
示例(明确):
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]}
输出:
ENUM_INDEX[OK] = 0
ENUM_INDEX[CANCEL] = 1
ENUM_INDEX[ERROR] = 2
ENUM_INDEX[CONFIRM] = 3
ENUM_INDEX[SAVE] = 4
ENUM_INDEX[EXIT] = 5
请注意,关联数组没有定义的顺序,但始终可以在以后排序。
答案 3 :(得分:1)
您可以合并以下几行:
for i in E_OK E_CANCEL E_ERROR E_CONFIRM E_SAVE E_EXIT; do declare -r ${i}=$((x++)); done
输出:
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