Bash:访问数组元素(异常行为)

时间:2018-09-26 10:16:58

标签: arrays bash

我要运行一个从1到12的循环,将当前循环号与预定义的数组匹配,然后输出匹配的数组。

每种类型的月份都有一个数组。

lm #has 4,6,9,11 
hm #has 1,3,5,7,8,10,12 
feb #special case, if its not an hm or lm, its feb

这是我当前的代码:

#!/bin/bash
lm=()
lm+=(4)
lm+=(6)
lm+=(9)
lm+=(11)

hm=()
hm+=(1)
hm+=(3)
hm+=(5)
hm+=(7)
hm+=(8)
hm+=(10)
hm+=(12)

feb=()
feb+=(2)

ld=(1 2)
hd=(1 2)
fd=(1 2)
for m in {1..12}
do
echo "current month is $m"
    if [[ " ${hm[*]} " == *"$m"* ]];
    then
        echo "high month"
    elif [[ " ${lm[*]} " == *"$m"* ]];
    then
        echo "low month"
    elif [[ " ${feb[*]} " = *"$m"* ]];
    then
        echo "feb"
    else
        echo "weird month input"
    fi
done

其输出:

$ ./old2.sh
current month is 1
high month
current month is 2
high month
current month is 3
high month
current month is 4
low month
current month is 5
high month
current month is 6
low month
current month is 7
high month
current month is 8
high month
current month is 9
low month
current month is 10
high month
current month is 11
low month
current month is 12
high month

查看 2 ,它显示为高月份( hm ),即31天。

我已注释掉将在数组中添加12或12月的行:

#!/bin/bash
lm=()
lm+=(4)
lm+=(6)
lm+=(9)
lm+=(11)

hm=()
hm+=(1)
hm+=(3)
hm+=(5)
hm+=(7)
hm+=(8)
hm+=(10)
#hm+=(12)

feb=()
feb+=(2)

ld=(1 2)
hd=(1 2)
fd=(1 2)
for m in {1..12}
do
echo "current month is $m"
    if [[ " ${hm[*]} " == *"$m"* ]];
    then
        echo "high month"
    elif [[ " ${lm[*]} " == *"$m"* ]];
    then
        echo "low month"
    elif [[ " ${feb[*]} " = *"$m"* ]];
    then
        echo "feb"
    else
        echo "weird month input"
    fi
done

新输出:

$ ./old2.sh
current month is 1
high month
current month is 2
feb
current month is 3
high month
current month is 4
low month
current month is 5
high month
current month is 6
low month
current month is 7
high month
current month is 8
high month
current month is 9
low month
current month is 10
high month
current month is 11
low month
current month is 12
weird month input

现在输出与预期的一样。

为什么我的脚本接受 2 作为 hm ,而不是应该接受 feb

1 个答案:

答案 0 :(得分:0)

问题似乎是您使用*"$m"*作为匹配模式,因此,当您尝试匹配2 y也匹配12时。

在算法中,您将整个数组用作字符串,并尝试匹配一个元素。一种快速而肮脏的解决方案是在比赛周围使用空格,例如:

for m in {1..12}
do
echo "current month is $m"
    if [[ " ${hm[*]} " == *" $m "* ]];
    then
        echo "high month"
    elif [[ " ${lm[*]} " == *" $m "* ]];
    then
        echo "low month"
    elif [[ " ${feb[*]} " == *" $m "* ]];
    then
        echo "feb"
    else
        echo "weird month input"
    fi
done

它将在那里工作,因为“ 2”与“ 12”不匹配。

但是我不认为这是最好的方法...不幸的是,bash没有在数组中查找元素的语法,但是如果您查看此答案https://stackoverflow.com/a/8574392/6316852,则有一个函数可以完全符合您的需求。

因此,另一种选择:

#!/bin/bash
lm=(4 6 9 11)
hm=(1 3 5 7 8 10 12)
feb=(2)

containsElement () {
  local e match="$1"
  shift
  for e; do [[ "$e" == "$match" ]] && return 0; done
  return 1
}

for m in {1..12}; do
    echo "current month is $m"
    if containsElement "$m" "${hm[@]}"; then
        echo "high month"
    elif containsElement "$m" "${lm[@]}"; then
        echo "low month"
    elif containsElement "$m" "${feb[@]}"; then
        echo "feb"
    else
        echo "weird month input"
    fi
done

希望有帮助