Bash

案例語句中的 AND 運算符

  • June 29, 2020

我有以下程式碼。

read -p "Enter a word: " word

case $word in
 [aeiou]* | [AEIOU]*)
         echo "The word begins with a vowel." ;;
 [0-9]*)
         echo "The word begins with a digit." ;;
 *[0-9])
         echo "The word ends with a digit." ;;
 [aeiou]* && [AEIOU]* && *[0-9])
         echo "The word begins with vowel and ends with a digit." ;;
  ????)
         echo "You entered a four letter word." ;;
  *)
         echo "I don't know what you've entered," ;;
esac

當我執行這個:

Enter a word: apple123
case2.sh: line 10: syntax error near unexpected token `&&'
case2.sh: line 10: `  [aeiou]* && [AEIOU]* && *[0-9])'

看起來 case 語句不支持 AND 運算符,而且我認為上述 case 語句中的 && 運算符在邏輯上是不正確的。

我知道我們可以使用 if else 來檢查輸入是否以元音和數字開頭。但我很好奇 case 是否有像 AND 運算符這樣的內置函式。

您是正確的,因為標准定義case不允許在模式中使用 AND 運算符。您也正確地說“以小寫元音開頭並以大寫元音開頭”不會匹配任何內容。另請注意,您的模式和解釋以數字測試的開頭/結尾反轉 - 使用模式[0-9]*將匹配以數字開頭的單詞,而不是以數字結尾的單詞。

一種方法是將您的測試組合成相同的模式,首先是最嚴格的:

case $word in
 ([AaEeIiOoUu]??[0-9]) echo it is four characters long and begins with a vowel and ends with a digit;;
 ([AaEeIiOoUu]*[0-9])  echo it is not four characters long begins with a vowel and ends with a digit;;
# ...
esac

另一種(冗長!)方法是嵌套您的case語句,每次都建立適當的響應。它是否以元音開頭,是或否?現在,它是否以數字結尾,是或否?這會很快變得笨拙,並且維護起來很煩人。

另一種方法是使用一系列case語句來建構適用語句的字元串(或數組);如果您想提供“負面”回饋(“單詞不以元音開頭”等),您甚至可以*為每個模式添加包羅萬象的模式。

result=""
case $word in
 [AaEeIiOoUu]*)
         result="The word begins with a vowel." ;;
esac

case $word in
 [0-9]*)
         result="${result} The word begins with a digit." ;;
esac

case $word in
 *[0-9])
         result="${result} The word ends with a digit." ;;
esac

case $word in
  ????)
         result="${result} You entered four characters." ;;
esac

printf '%s\n' "$result"

舉些例子:

$ ./go.sh
Enter a word: aieee
The word begins with a vowel.
$ ./go.sh
Enter a word: jeff42
The word ends with a digit.
$ ./go.sh
Enter a word: aiee
The word begins with a vowel. You entered four characters.
$ ./go.sh
Enter a word: 9arm
The word begins with a digit. You entered four characters.
$ ./go.sh
Enter a word: arm9
The word begins with a vowel. The word ends with a digit. You entered four characters.

或者,bash 擴展了case語句的語法以允許選擇多個模式,如果您以以下方式結束模式;;&

shopt -s nocasematch
case $word in
 [aeiou]*)
         echo "The word begins with a vowel." ;;&
 [0-9]*)
         echo "The word begins with a digit." ;;&
 *[0-9])
         echo "The word ends with a digit." ;;&
  ????)
         echo "You entered four characters." ;;
esac

請注意,我刪除了*包羅萬象的模式,因為當以這種方式通過模式時,它會匹配任何東西。Bash 還有一個名為 的 shell 選項nocasematch,我在上面設置了它,它可以對模式進行不區分大小寫的匹配。這有助於減少冗餘——我刪除了| [AEIOU]*模式的一部分。

舉些例子:

$ ./go.sh
Enter a word: aieee
The word begins with a vowel.
$ ./go.sh
Enter a word: jeff42
The word ends with a digit.
$ ./go.sh
Enter a word: aiee
The word begins with a vowel.
You entered four characters.
$ ./go.sh
Enter a word: 9arm
The word begins with a digit.
You entered four characters.
$ ./go.sh
Enter a word: arm9
The word begins with a vowel.
The word ends with a digit.
You entered four characters.

引用自:https://unix.stackexchange.com/questions/549165