2014-10-16 27 views
1

我正在使用bash腳本,但我無法弄清爲什麼我會看到某種行爲。爲什麼bash在爲數組的一部分搜索數組時返回true?

我宣佈月份名稱的數組,像這樣:

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%匹配的?

回答

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 
+0

這樣做了;我使用的是bash 4.1,你的建議完美運行。謝謝! – 2014-10-16 20:09:25

3

這是因爲"${months[*]}"擴展爲用空格連接的數組成員的單個字符串,並且您匹配該字符串。

您可以通過添加空格解決這個問題:

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

編輯

以上的4.3.11(1)-release對我的作品(你所有的例子)(x86_64的-pc-linux-gnu)4.2.24(1)-release(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: 要使用空間過濾掉投入,從而防止「二月martch」等:

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

謝謝您的回覆,但加入空間似乎不能解決問題。 – 2014-10-16 19:58:59

+0

您是將它們添加到左側還是右側? – PSkocik 2014-10-16 20:03:25

+0

是的,我在兩邊添加了它們。 – 2014-10-16 20:05:02

相關問題