これが私が持っているものです。 3つの入力を検証しようとしています。最初と2番目の入力は正しい入力を必要としません。何が問題なの?
#!/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を入力しただけで、ユーザーに役職と姓を再入力するように強制したくないので、ユーザーから読み取るすべての項目に1つの大きなループの代わりに3つの入力ループが必要です。 。
コードは不必要に反復的なので、3つのループで書き直すと返品不要な繰り返しをしてください。別個の入力機能があればもっと便利です。
以下のスクリプトではこれを行いました。入力関数は、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
printf
最後の3行を次に変更して、スクリプト自体でこれを行うこともできます。
# 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"
ユーザーが入力した入力を使用すると、スクリプトユーザーが現在のディレクトリにある任意のファイルを上書きできます(権限がこれを許可すると仮定)。