我创建了一个 while 循环来获取用户输入并在出现错误时重复提示。
while true; do
read -p "Enter hostname : " fqdn
pattern="(^[^\.]*\.[^\.]*\.[^\.]*$)"
if [[ -z "$fqdn" ]]; then #if fqdn input is empty
echo "Error! Hostname cannot be empty"
continue
elif [[ ! "${fqdn}" =~ ${pattern} ]]; then
echo "Error! Format incorrect"
continue
else
echo "hostname is $fqdn"
break
fi
done
我的目标:
- 的情况下如果/elif说明如何仅显示提示两次然后退出。
- 有没有办法可以改进上面的 while 循环,例如使用 案例开关。我觉得大小写切换很难理解?
操作系统:Ubuntu 20.04(无头)
答案1
以下bash
脚本从用户读取字符串并测试该字符串是否满足您似乎想要强制执行的主机名的条件。
语句中使用的两个模式中的第一个case
测试中间没有字符的两个点的病态情况(这是我们不采取行动的模式)。我们测试第二个模式是否包含至少两个点且两端都没有点的字符串。fdqn
仅当第二个模式与字符串匹配时,主机名变量才会设置为该字符串。请注意,该字符串foo..bar
与第二个模式匹配,这就是为什么我们抢先将双点子字符串与第一个模式匹配的原因。
#!/bin/bash
unset -v count fdqn
while true; do
read -p 'Enter hostname: ' -r
case $REPLY in (*..*) ;; ([!.]*.*.*[!.]) fdqn=$REPLY; break; esac
echo 'Invalid format' >&2
count=$(( count + 1 ))
[ "$count" -eq 2 ] && break
done
if [ -z "$fdqn" ]; then
echo 'No valid hostname entered' >&2
exit 1
fi
printf 'The hostname is "%s"\n' "$fdqn"
该count
变量跟踪用户尝试输入字符串的次数。如果该变量的值达到 2,我们就会跳出循环。
这里没有真正需要使用case
语句,除非您想让它成为可移植sh
脚本(在这种情况下,您必须以read
不同的方式执行该语句)。使用 globbing 运算==
符时bash
,case
语句将如下所示。
if [[ $REPLY == *..* ]]; then
:
elif [[ $REPLY == [!.]*.*.*[!.] ]]; then
fdqn=$REPLY
break
fi
&&
如果第一个测试被否定,也可以使用这两个测试来连接。
if [[ $REPLY != *..* ]] && [[ $REPLY == [!.]*.*.*[!.] ]]; then
fdqn=$REPLY
break
fi
如果您想避免获得包含三个点的主机名,请确保$REPLY
does not match *.*.*.*
,就像它不应该 match 一样*..*
。
答案2
我想到了一个替代方案,我相信它可以改进:
# declare the pattern outside the loop
pattern="(^[^.]*\.[^.]*\.[^.]*$)"
# declare a counter for failed attempts
c=0
while true; do
# if counter is equal to 2 exit
[[ $c -eq 2 ]] && echo "Two failed attempts. Exiting" && exit
read -p "Enter hostname : " fqdn
if [[ -z "$fqdn" ]]; then
echo "Error! Hostname cannot be empty"
((c++)) # increment the counter
continue
elif [[ ! "${fqdn}" =~ ${pattern} ]]; then
echo "Error! Format incorrect"
((c++)) # increment the counter
continue
fi
# this lines will be executed only if the conditions passed
echo "hostname is $fqdn"
break
done
该case
构造不使用正则表达式,因此对于复杂的匹配,最好使用if elif..
语句。