我正在制作一个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%匹配?
答案 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