smc*_*smc 6 shell bash shell-script case
我有以下代码。
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
Run Code Online (Sandbox Code Playgroud)
当我运行这个:
Enter a word: apple123
case2.sh: line 10: syntax error near unexpected token `&&'
case2.sh: line 10: ` [aeiou]* && [AEIOU]* && *[0-9])'
Run Code Online (Sandbox Code Playgroud)
看起来 case 语句不支持 AND 运算符,而且我认为上面 case 语句中的 && 运算符在逻辑上是不正确的。
我知道我们可以使用 if else 来检查输入是否以元音和数字开头。但我很好奇 case 是否有任何内置函数,如 AND 运算符。
Jef*_*ler 11
您是正确的,因为标准定义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
Run Code Online (Sandbox Code Playgroud)
另一种(冗长的!)方法是嵌套你的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"
Run Code Online (Sandbox Code Playgroud)
举些例子:
$ ./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.
Run Code Online (Sandbox Code Playgroud)
或者,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
Run Code Online (Sandbox Code Playgroud)
请注意,我删除了*全能模式,因为当以这种方式通过模式时,它会匹配任何内容。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.
Run Code Online (Sandbox Code Playgroud)
为了完整起见,虽然case有|OR 运算符,但它没有 AND 运算符,但如果使用带有扩展 glob 运算符(ksh、zsh、bash)的 shell,您可以在模式语法中实现 AND :
ksh93的@(x&y&z)运营商:
case $string in
( @({12}(?)&~(i:[aeiou]*)&*[0123456789]) )
echo is 12 characters long AND starts with a vowel AND ends in a decimal
esac
Run Code Online (Sandbox Code Playgroud)
zsh(使用~(AND-NOT)结合^(NOT)):x~^y~^z
set -o extendedglob
case $string in
( ?(#c12)~^(#i)[aeiou]*~^*[0-9] )
echo is 12 characters long AND starts with a vowel AND ends in a decimal
esac
Run Code Online (Sandbox Code Playgroud)
ksh88, bash, 使用带 OR ( !(!(x)|!(y)|!(z))) 的双重否定
shopt -s extglob # bash only
case $string in
( !(!(????????????)|!([aAeE?iI?oOuU]*)|!(*[0123456789])) )
echo is 12 characters long AND starts with a vowel AND ends in a decimal
esac
Run Code Online (Sandbox Code Playgroud)
在任何情况下,请记住,除了在 zsh 中范围始终基于代码点值[0-9]之外,在 POSIX/C 语言环境之外不能可靠地使用类似的范围(因此是[0123456789]上面的替代)。
ksh93 和 zsh 的不区分大小写匹配运算符(~(i)和(#i))尊重区分大小写比较的语言环境。例如,在GNU系统上的土耳其语言环境,(#i)[aeiou]将匹配上?,而不是I(因为大写i是?那里)。为了在不考虑语言环境的情况下获得一致的结果,您可能需要像 ksh88/bash 方法那样对所有可能的值进行硬编码。
| 归档时间: |
|
| 查看次数: |
916 次 |
| 最近记录: |