Eu tenho as seguintes linhas em um script bash:
while true; do
DATE=date
FORMAT="%Y%m%d"
read -p "Enter start date (YYYYMMDD) " STARTDATE
if date=$(date -d "$STARTDATE" +'+%Y%m%d'); then
start_date=`$DATE +$FORMAT -d $STARTDATE`
echo $start_date
break
fi
echo "Please use right format (YYYYMMDD) "
done
Isso funciona bem desde que a entrada seja de 8 números (por exemplo, aceita "20210901" e rejeita "20213131"). No entanto, quando a entrada está totalmente desativada (por exemplo, "a" ou "nonsense"), ela simplesmente leva a data de hoje. Como o código poderia ser modificado para uma verificação mais rigorosa do formato?
O código modificado lê:
valid=0
while true; do
DATE=date
FORMAT="%Y%m%d"
read -p "Enter start date (YYYYMMDD) " initialdate
if date=$(date -d "$initialdate" +'+%Y%m%d'); then
start_date=`$DATE +$FORMAT -d $initialdate`
if [[ "$start_date" =~ ^[[0123456789]]{8}$ ]]
then
valid=1
echo "valid";
echo $start_date
break
else
echo "Invalid format"
fi
fi
echo "Please use right format (YYYYMMDD) "
done
Como você pode reduzir a tarefa a uma verificação adicional exigindo que a entrada consista em exatamente 8 dígitos e esteja usando o Bash, você pode aproveitar o operador de comparação de expressão regular:
Isso verificará se o conteúdo de está de
$startdate
acordo com uma expressão regular que consiste em exatamente oito dígitos.Você pode combinar isso da seguinte forma:
Como uma regra geral:
shellcheck
, também disponível como programa autônomo em muitas distribuições Linux, para verificar seus scripts de shell.$PATH
por acidente.Uma maneira comum de fazer validação de entrada é usar um loop infinito que você interrompe assim que a entrada for validada.
Nesse caso, "validado" significa que a string de entrada contém apenas oito dígitos e que o GNU
date
pode usar essa data como um argumento de opção para sua-d
opção.Com
bash
, poderíamos escrever isso comoIsso lê a data no início do nosso loop e, em seguida, testa-a com uma expressão regular que corresponderá se a string contiver apenas oito dígitos. Se esse teste passar, a string também será testada com GNU
date
. Se tudo correr bem, o loop é encerrado por meio de umabreak
instrução.Em
sh
, precisamos substituir a correspondência de expressão regular por uma correspondência de padrão de shell:O teste aqui primeiro testa se a string contém qualquer outro caractere além de um dígito. Se esse teste falhar, o próximo teste será para exatamente oito caracteres. Se esse teste for bem-sucedido, temos uma string de oito dígitos e testamos com GNU
date
e saímos do loop se a data estiver correta.Ou sem o loop infinito, e assumindo o
date(1)
comando do BSD:A
${REPLY}0000
sintaxe é necessária porque o BSDdate
deseja um YmdHM completo, mas o padrão do HM0000
é suficiente.