为什么在搜索数组中元素的一部分时bash返回true?

时间:2014-10-16 19:43:06

标签: bash

我正在制作一个bash脚本,但我无法弄清楚为什么我会看到某种行为。

我声明了一个月份名称数组,如下所示:

declare -a months=("january" "february" "march" "april" "may" "june" "july" "august" "september" "october" "november" "december")

然后我有一个循环,提示用户输入一个月。如果他们输入的月份无效,则会继续提示他们再过一个月。循环如下:

month=
while [[ -z ${month} ]]
do
echo -e "\nPlease enter a month, for example, \"November\"."
read month
if [[ ! "${months[*]}" =~ "${month,,}" ]] ; then
    echo -e "\nInvalid month; please check your spelling and try again."
    month=
fi
done

如果我输入的字符串与" months"中的条目完全不同,则此方法有效。例如,如果我输入" septiembre,"该计划按预期运作。

但是,如果我输入一个月份字符串的一部分,例如," nov"或者" mber,"该程序将其视为有效并继续。

当用户输入的输入与数组中字符串的一部分匹配时,为什么bash返回true?为什么不查看字符串是否100%匹配?

2 个答案:

答案 0 :(得分:3)

这是因为"${months[*]}"扩展为使用空格连接的数组成员的单个字符串,并且您将与该字符串匹配。

你可以通过添加空格来解决这个问题:

[[ ! " ${months[*]} " =~ " ${month,,} " ]]

修改

上面的内容(适用于所有示例)适用于 4.3.11(1)-release(x86_64-pc-linux-gnu) 4.2.24(1) - 发布(i686-pc-linux-gnu)。整个代码如下(仅添加了空格)。

declare -a months=("january" "february" "march" "april" "may" "june" "july" "august" "september" "october" "november" "december")
month=
while [[ -z ${month} ]]
do
echo -e "\nPlease enter a month, for example, \"November\"."
read month
if [[ ! " ${months[*]} " =~ " ${month,,} " ]] ; then
    echo -e "\nInvalid month; please check your spelling and try again."
    month=
fi
done

<强> EDIT2 :     用空格过滤掉输入,从而防止2月2日马丁&#34;等的误报:

if [[ "${month}" =~ " " || ! " ${months[*]} " =~ " ${month,,} " ]]; then

答案 1 :(得分:3)

您正在使用正则表达式运算符,因此(作为一个简单的示例)“1月2月”将匹配正则表达式jan(甚至正则表达式ry fe)。为了检查输入是否是数组的元素,请使用关联数组。

declare -A months=([january]=1 [february]=2 ...)

如果您使用的是bash 4.2或更高版本,那就像

一样简单
if [[ ! -v months[${month,,}] ]]; then

对于bash 4.0或4.1,您可以使用

if [[ -z ${months[${month,,}]} ]]; then