Das ist, was ich habe. Ich versuche, 3 Eingaben zu validieren. Bei der ersten und der zweiten Eingabe werde ich nicht aufgefordert, die korrekte Eingabe einzugeben. Was ist falsch?
#!/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
Antwort1
Ihr SkriptAusgängesobald für den Titel oder Nachnamen eine ungültige Eingabe erfolgt, was die Schleife nutzlos macht. Verwenden Sie diese Option, continue
um eine Iteration erneut auszuführen.
Sie möchten den Benutzer jedoch nicht zwingen, seinen Titel und Nachnamen erneut einzugeben, nur weil er eine ungültige ID eingegeben hat. Daher benötigen Sie drei Eingabeschleifen anstelle einer großen Schleife; eine Schleife für alles, was Sie vom Benutzer lesen.
Ihr Code ist unnötig repetitiv und das Umschreiben in drei Schleifen würdeAuchunnötige Wiederholungen. Es wäre bequemer, eine separate Eingabefunktion zu haben.
Im folgenden Skript habe ich das getan. Die Eingabefunktion get_input
nimmt ein „Label“ (eine Beschreibung dessen, was der Benutzer eingeben soll) und ein Muster, dem jedes Zeichen in der Eingabe entsprechen muss. Die get_input
Funktion gibt die gültige Zeichenfolge auf der Standardausgabe aus, weshalb wir sie im Hauptteil des Skripts innerhalb einer Befehlsersetzung aufrufen.
Ich habe auch die String-Validierung in eine eigene Funktion verschoben. Dies dient dazu, die get_input
Funktion übersichtlicher zu gestalten und die Validierungslogik von der Eingabelogik zu trennen.
Die Validierung verwendet denselben Ansatz wie Sie, d. h. sie löscht alle gültigen Zeichen aus der Zeichenfolge und prüft dann, ob noch Zeichen übrig sind. In diesem Fall besteht die Zeichenfolge die Validierung nicht.
#!/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"
Um beispielsweise auch Punkte im Titel oder Nachnamen zuzulassen, ändern Sie das Muster von [[:alpha:] ]
in [[:alpha:]. ]
. Oder Sie können noch weniger restriktiv sein und [![:digit:]]
alle nicht-stelligen Zeichen (einschließlich Satzzeichen usw.) zulassen.
Um die Ausgabe in einer Datei mit demselben Namen wie der Benutzer zu speichern, der das Skript ausführt, leiten Sie die Ausgabe des Skripts selbst um:
$ ./script.sh >"$USER.txt"
Dadurch wird das Skript ausgeführt und die Ausgabe in eine Datei namens umgeleitet $USER.txt
, wobei $USER
der Benutzername des aktuellen Benutzers ist (diese Variable und $LOGNAME
sind normalerweise bereits von der Shell und/oder dem System festgelegt).
Sie können dies auch innerhalb des Skripts selbst tun, indem Sie die letzten drei printf
Zeilen in
# Print what we got.
{
printf 'Title = "%s"\n' "$title"
printf 'Surname = "%s"\n' "$surname"
printf 'ID = "%s"\n' "$id"
} >"$USER.txt"
Oder, wenn Sie den vom Benutzer gelesenen „Nachnamen“ im Skript verwenden möchten:
# Print what we got.
{
printf 'Title = "%s"\n' "$title"
printf 'Surname = "%s"\n' "$surname"
printf 'ID = "%s"\n' "$id"
} >"$surname.txt"
ZuAuchZum Drucken auf dem Terminal verwenden Sie tee
:
# Print what we got.
{
printf 'Title = "%s"\n' "$title"
printf 'Surname = "%s"\n' "$surname"
printf 'ID = "%s"\n' "$id"
} | tee "$surname.txt"
Beachten Sie, dass die Verwendung der vom Benutzer eingegebenen Daten es dem Benutzer des Skripts potenziell ermöglicht, beliebige Dateien im aktuellen Verzeichnis zu überschreiben (sofern die Berechtigungen dies zulassen).