我想要一个变量,其值应该在已定义的范围内。
例如。
变量DAY = $ 1
只应获得Mon,Tue,Wed,Then,Fri,Sat,Sun等值。
如果用户输入其他内容,则不会接受。
我知道我可以通过定义数组或通常是存储所有日期的变量,然后检查变量DAY在" for或while"循环。
但我想要没有循环的最简单方法。
提前致谢。
答案 0 :(得分:2)
使用扩展的glob支持来完全匹配一个选项列表。
range="Mon|Tue|Wed|Thu|Fri"
read day
if [[ $day = @($range) ]]; then
echo "$day is valid"
else
echo "$day is not valid"
fi
答案 1 :(得分:1)
如果不使用循环,您可以执行以下操作:
EOL=$'\n'
arr=(Mon Tue Wed Thus Fri Sat Sun)
read -p 'Enter day value: ' day
Tue
[[ $(printf "$EOL%s$EOL" "${arr[@]}") == *"$EOL$day$EOL"* ]] &&
echo "in range" || echo "not in range"
in range
read -p 'Enter day value: ' day
ue We
[[ $(printf "$EOL%s$EOL" "${arr[@]}") == *"$EOL$day$EOL"* ]] &&
echo "in range" || echo "not in range"
not in range
答案 2 :(得分:0)
稍微扩大anubhava的答案:
arr=(Mon Tue Wed Thus Fri Sat Sun)
read -p 'Enter day value: ' day
case "${arr[@]}" in *"$day"*) echo "in range";; esac
基本上,这是构建一个数组,将其转换为字符串,并在其上进行模式匹配。
在case
表达式的上下文中,"${arr[@]}"
和"${arr[*]}"
之间没有区别;我个人会坚持使用*
,这使您更清楚地构建一个大字符串而不是单独的字符串列表。
使用这组特定的值,您不必担心子字符串重叠,但上述检查仍然过于宽容。例如,如果您输入u
,则会在范围"中将其视为"。这可能不是你想要的。
更精确的测试将是这样的:
case "${arr[*]}" in
"$day "*|*" $day "*|*" $day") echo "in range";;
*) echo "not in range";;
esac
这仍然允许用户输入多天,因为" Mon Tue"或类似的;在此特定情况下,一种简单的方法是将read
行从read day
更改为read day _
。
"$day "*
模式将在数组的开头匹配(因此,如果他们在这种情况下输入Mon
)。 *" $day"
模式将匹配数组末尾(Fri
),*" $day "*
模式将与其余模式匹配。除了精确的日期字符串之外别无其他。
另外,在这里您可以看到如何处理else
案例 - *
的模式匹配任何尚未与其他内容匹配的内容,因此它相当于else
中的case
。
答案 3 :(得分:0)
实际上不需要阵列。
read -r day
case ' Mon Tue Wed Thu Fri Sat Sun ' in
*" $day "*)
echo "in range";;
*) echo "not in range";;
esac
注意字符串表达式周围的空格。
如果你需要严格,你应该拒绝“星期三”,这是不行的。它需要第二个case
包装,它很笨重但不完全笨重。