驗證 3 個輸入的腳本
這就是我所擁有的。我正在嘗試驗證 3 個輸入。第一個和第二個輸入不要求我輸入正確的輸入。怎麼了?
#!/bin/bash while : do echo "Please enter your tittle:" read TITTLE echo "Please enter your surname:" read SURNAME echo "Please enter your ID No." read ID if [ "$TITTLE" = "" ] || [ "${TITTLE//[!0-9]}" != "" ]; then echo "Enter your valid tittle without special characters." echo "Please try again." exit 1 fi if [ "$SURNAME" = "" ] || [ "${SURNAME//[!0-9]}" != "" ]; then echo "Enter your valid surname without special characters." echo "Please try again." exit 1 fi if [ "$ID" = "" ] || [ "${ID//[0-9]}" != "" ]; then echo "Enter your valid ID No. without special characters." echo "Please try again" else echo "Thank you" $TITTLE $SURNAME break fi done
一旦為標題或姓氏提供無效輸入,您的腳本就會*退出,這會使循環無用。*用於
continue
重新進行迭代。但是,您不想僅僅因為使用者輸入了無效的 ID 而強制使用者再次輸入他們的頭銜和姓氏,因此您將需要三個輸入循環而不是一個大循環;你從使用者那裡讀到的每一件事都有一個循環。
您的程式碼是不必要的重複,將其重寫為三個循環也將是不必要的重複。有一個單獨的輸入功能會更方便。
在下面的腳本中,我已經做到了。輸入函式
get_input
採用“標籤”(使用者應輸入內容的一些描述)和輸入中每個字元必須匹配的模式。該get_input
函式在標準輸出上輸出有效字元串,這就是我們在腳本主要部分的命令替換中呼叫它的原因。我還將字元串驗證移到了它自己的函式中。這是為了使
get_input
函式更簡潔,並將驗證邏輯與輸入邏輯分開。驗證使用與您使用相同的方法,即它從字元串中刪除所有有效字元,然後測試是否還有任何字元,在這種情況下,字元串驗證失敗。
#!/bin/bash # Succeeds if the first argument is non-empty and only # consists of characters matching the pattern in the # second argument. is_valid () { local string pattern string=$1 pattern=$2 [ -n "$string" ] && [ -z "${string//$pattern}" ] } # Asks user for input until the given string is valid. # The first argument is a text string describing what # the user should enter, and the second argument is a # pattern that all characters in the inputted data much # match to be valid. get_input () { local label pattern local string label=$1 pattern=$2 while true; do read -r -p "Please enter $label: " string if is_valid "$string" "$pattern"; then break fi # Complain on the standard error stream. printf 'Invalid input, try again\n' >&2 done printf '%s\n' "$string" } # Get data from user. title=$( get_input 'your title' '[[:alpha:] ]' ) # title: only letters and spaces surname=$( get_input 'your surname' '[[:alpha:] ]' ) # surname: same as title id=$( get_input 'your ID no.' '[[:digit:]]' ) # ID: only digits # Print what we got. printf 'Title = "%s"\n' "$title" printf 'Surname = "%s"\n' "$surname" printf 'ID = "%s"\n' "$id"
要在標題或姓氏中也允許使用點,請將模式從 更改
[[:alpha:] ]
為[[:alpha:]. ]
。或者,您可以減少限制並使用[![:digit:]]
以允許任何非數字字元(包括標點符號等)要將輸出保存在與執行腳本的使用者同名的文件中,請重定向腳本本身的輸出:
$ ./script.sh >"$USER.txt"
這將執行腳本並將輸出重定向到一個名為 的文件
$USER.txt
,其中$USER
是目前使用者的使用者名(這個變數和$LOGNAME
,通常已經由 shell 和/或系統設置)。
printf
您也可以通過將最後三行更改為腳本本身來執行此操作# Print what we got. { printf 'Title = "%s"\n' "$title" printf 'Surname = "%s"\n' "$surname" printf 'ID = "%s"\n' "$id" } >"$USER.txt"
或者,如果您想在腳本中使用從使用者那裡讀取的“姓氏”:
# Print what we got. { printf 'Title = "%s"\n' "$title" printf 'Surname = "%s"\n' "$surname" printf 'ID = "%s"\n' "$id" } >"$surname.txt"
要列印到終端,請使用
tee
:# Print what we got. { printf 'Title = "%s"\n' "$title" printf 'Surname = "%s"\n' "$surname" printf 'ID = "%s"\n' "$id" } | tee "$surname.txt"
請注意,使用使用者提供的輸入可能允許腳本使用者覆蓋目前目錄中的任意文件(假設權限允許這樣做)。