如何评估数组中项目的优先级,以便只处理存在的最高优先级项目?让我尝试解释一下,如果我有一个数组
set -A array low medium none high
该数组是运行命令创建的,其中该数组可以包含任何或所有列出的元素。我想要做的是评估它找到的任何最高优先级元素,并停止循环遍历数组而不退出脚本。换句话说,如果存在 low 和 high,则仅对 high 求值,而不继续循环遍历数组。如果存在中和低,则仅对中进行评估并停止循环。
到目前为止,我发现执行此操作的唯一方法是按照我查找元素的顺序输入多个循环的可怕组合。如果找到该元素,那么我会在它进入下一个循环之前退出,但如果有意义的话,我不需要退出或返回。
这是一个示例:
#!/bin/sh
set -A array low medium none high
high() {
printf "High\n"
}
medium() {
printf "Medium\n"
}
low() {
printf "Low\n"
}
none() {
printf "None\n"
}
for i in ${array[*]}; do if [ ${i} = "high" ]; then high; exit 0; fi done
for i in ${array[*]}; do if [ ${i} = "medium" ]; then medium; exit 0; fi done
for i in ${array[*]}; do if [ ${i} = "low" ]; then low; exit 0; fi done
for i in ${array[*]}; do if [ ${i} = "none" ]; then none; exit 0; fi done
使用上面的代码,如果您更改数组并取出任何元素,它几乎被迫根据我评估的层次结构进行评估。如果高、低、中、不存在,它将打印高并退出。如果您取出高和中,它将打印低并退出。
我有另一个脚本正在读取此内容,因此如果我退出,它会退出整个链,包括加载此内容的父级,因此我试图弄清楚一旦发现缺少的最高优先级,如何停止评估数组中的任何元素的更好的描述。
如果我取出存在,它只会命中每个循环并给出每个循环的输出。我尝试使用 elif 和 else 没有成功,但它总是评估每个元素。
有任何想法吗?是否有可能在不退出脚本的情况下停止它?
答案1
#!/bin/ksh
high () echo High
medium () echo Medium
low () echo Low
none () echo None
set -A array low medium none high
for level in high medium low none; do
for elem in "${array[@]}"; do
if [ "$elem" = "$level" ]; then
"$level"
break 2
fi
done
done
这是一个双循环。外层循环按重要性顺序循环各个级别。内部循环遍历数组中的元素,查找等于当前级别的元素。
如果找到与当前级别对应的元素,则调用与该级别同名的函数并退出两个循环。
请注意,在一般情况下,您需要循环"${array[@]}"
而不是${array[*]}
使用[*]
(并将扩展不加引号)会在数组中的字符串上进行分词和文件名通配。该表达式"${array[@]}"
将扩展到数组中单独引用的元素array
。
$elem
避免分词和文件名通配也是引用两者以及$level
比较它们等的原因。
一种可能更快的方法是首先创建一个关联数组,并将数组中的元素作为键,然后在其中进行键查找:
#!/bin/ksh
high () echo High
medium () echo Medium
low () echo Low
none () echo None
array=( low medium none high )
typeset -A lookup
for elem in "${array[@]}"; do
lookup["$elem"]=1
done
for level in high medium low none; do
if [ -n "${lookup[$level]}" ]; then
"$level"
break
fi
done
这避免了双循环,如果数组或级别数或两者都非常长,则双循环将很有用。
我还切换到了更常见的=(...)
数组赋值形式。