Bash
用於使用者輸入的 Bash While 循環和帶有最大嘗試次數計數器的錯誤提示
我創建了一個 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
我的目標:
- 在if/elif語句的情況下,如何只顯示兩次提示然後退出。
- 有沒有辦法可以改進上述 while 循環,例如使用 case switch。我覺得 case switch 很難理解?
作業系統:Ubuntu 20.04(無頭)
這是我心中的一個替代方案,我相信它可以改進:
# 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..
語句。
以下
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
。使用 中的萬用字元==
,語句將如下所示。bash``case
if [[ $REPLY == *..* ]]; then : elif [[ $REPLY == [!.]*.*.*[!.] ]]; then fdqn=$REPLY break fi
&&
如果第一個被否定,這兩個測試也可以使用。if [[ $REPLY != *..* ]] && [[ $REPLY == [!.]*.*.*[!.] ]]; then fdqn=$REPLY break fi
如果您想避免獲得包含三個點的主機名,請確保
$REPLY
不匹配*.*.*.*
,就像它不應該匹配一樣*..*
。