這就是我所擁有的。我正在嘗試驗證 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
答案1
你的腳本退出一旦為標題或姓氏提供了無效輸入,這將使循環變得無用。用於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"
請注意,使用使用者給出的輸入可能允許腳本使用者覆蓋目前目錄中的任意檔案(假設權限允許這樣做)。