Isso é o que eu tenho. Estou tentando validar 3 entradas. A primeira e a segunda entradas não me pedem para inserir a entrada correta. O que está errado?
#!/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
Responder1
Seu roteirosaídasassim que uma entrada inválida for fornecida para o título ou sobrenome, o que torna o loop inútil. Use continue
para refazer uma iteração.
No entanto, você não deseja forçar o usuário a inserir seu título e sobrenome novamente apenas porque inseriu um ID inválido; portanto, serão necessários três loops de entrada em vez de um grande loop; um loop para cada coisa que você lê do usuário.
Seu código é desnecessariamente repetitivo e reescrevê-lo como três loops seriamtambémser desnecessariamente repetitivo. Seria mais conveniente ter uma função de entrada separada.
No script a seguir eu fiz isso. A função de entrada get_input
recebe um "rótulo" (alguma descrição do que o usuário deve inserir) e um padrão que cada caractere na entrada deve corresponder. A get_input
função gera a string válida na saída padrão, e é por isso que a chamamos em uma substituição de comando na parte principal do script.
Também movi a validação da string para sua própria função. Isso torna a get_input
função mais limpa e separa a lógica de validação da lógica de entrada.
A validação usa a mesma abordagem que você usa, ou seja, exclui todos os caracteres válidos da string e então testa se ainda há caracteres restantes, caso em que a string falha na validação.
#!/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"
Para também permitir, por exemplo, pontos no título ou sobrenome, altere o padrão de [[:alpha:] ]
para [[:alpha:]. ]
. Ou você pode ser ainda menos restritivo e [![:digit:]]
permitir qualquer caractere que não seja um dígito (incluindo sinais de pontuação, etc.)
Para salvar a saída em um arquivo com o mesmo nome do usuário que está executando o script, redirecione a saída do próprio script:
$ ./script.sh >"$USER.txt"
Isso executaria o script e redirecionaria a saída para um arquivo chamado $USER.txt
, onde $USER
é o nome de usuário do usuário atual (esta variável, e $LOGNAME
, geralmente já está definida pelo shell e/ou pelo sistema).
Você também pode fazer isso dentro do próprio script, alterando as três últimas printf
linhas para
# Print what we got.
{
printf 'Title = "%s"\n' "$title"
printf 'Surname = "%s"\n' "$surname"
printf 'ID = "%s"\n' "$id"
} >"$USER.txt"
Ou, se quiser usar o "sobrenome" lido do usuário no script:
# Print what we got.
{
printf 'Title = "%s"\n' "$title"
printf 'Surname = "%s"\n' "$surname"
printf 'ID = "%s"\n' "$id"
} >"$surname.txt"
Paratambémimprima no terminal, use tee
:
# Print what we got.
{
printf 'Title = "%s"\n' "$title"
printf 'Surname = "%s"\n' "$surname"
printf 'ID = "%s"\n' "$id"
} | tee "$surname.txt"
Observe que usar a entrada fornecida pelo usuário permite potencialmente que o usuário do script substitua arquivos arbitrários no diretório atual (desde que as permissões permitam isso).