Interrompendo um loop while [RESOLVIDO]

1. Interrompendo um loop while [RESOLVIDO]

Carlos Vinícius
cviniciusaraujo

(usa Ubuntu)

Enviado em 23/05/2020 - 23:27h

Pessoal, boa noite!

O código logo abaixo é um trecho editado de um projeto que eu estou desenvolvendo. Eu montei um "sisteminha" usando while e read para que cada caractere digitado pelo usuário seja verificado e que se caso for um caractere divergente do que é solicitado seja retornada uma mensagem de erro.

Como os caracteres são verificados um por vez, se eu colocar um break dentro do if abaixo de um else, o loop encerra e o valor da variável _USER será apenas o primeiro caractere digitado pelo usuário, sendo assim, não tem como o usuário terminar de digitar o que ele quer...

Alguém poderia me dá uma ajuda de como eu poderia finalizar o loop pressionando a tecla ENTER ou algo semelhante? Ou uma outra forma?


#!/bin/bash

clear
tput civis

while :; do
tput cup 1
read -p "Nome de usuário: " -n"$[${#_USER} + 1]" -e -i "$_USER" _USER
if echo "$_USER" | grep -q '[^a-z A-Z 0-9 ._-]'; then
tput cup 1 40
echo "Não foi possível criar o usuário!"
continue
fi
done



  


2. Re: Interrompendo um loop while

Marcelo Oliver
msoliver

(usa Debian)

Enviado em 24/05/2020 - 00:09h

cviniciusaraujo escreveu:

Pessoal, boa noite!

O código logo abaixo é um trecho editado de um projeto que eu estou desenvolvendo. Eu montei um "sisteminha" usando while e read para que cada caractere digitado pelo usuário seja verificado e que se caso for um caractere divergente do que é solicitado seja retornada uma mensagem de erro.

Como os caracteres são verificados um por vez, se eu colocar um break dentro do if abaixo de um else, o loop encerra e o valor da variável _USER será apenas o primeiro caractere digitado pelo usuário, sendo assim, não tem como o usuário terminar de digitar o que ele quer...

Alguém poderia me dá uma ajuda de como eu poderia finalizar o loop pressionando a tecla ENTER ou algo semelhante? Ou uma outra forma?


#!/bin/bash

clear
tput civis

while :; do
tput cup 1
read -p "Nome de usuário: " -n"$[${#_USER} + 1]" -e -i "$_USER" _USER
if echo "$_USER" | grep -q '[^a-z A-Z 0-9 ._-]'; then
tput cup 1 40
echo "Não foi possível criar o usuário!"
continue
fi
done

Boa noite cviniciusaraujo.
-n"$[${#_USER} + 1]"
Faz com que a variável "não tenha fim...."
Segue sugestão:
#!/bin/bash
clear
tput civis
while :; do Unset _USER;
tput cup 1
read -p "Nome de usuário: " -e -i "$_USER" _USER
if grep -q '[^a-z A-Z 0-9 ._-]' <<< "$_USER"; then
tput cup 1 40
echo "Não foi possível criar o usuário! $_USER"
else
echo "USER: $_USER OK"
tput reset
break;
fi
done



______________________________________________________________________
Importante: echo -e "\n$(lynx --dump goo.gl/a9KeFc|sed -nr '/^[ ]+Se/,/dou.$/p')\n"
Att.: Marcelo Oliver
______________________________________________________________________


3. Re: Interrompendo um loop while

Carlos Vinícius
cviniciusaraujo

(usa Ubuntu)

Enviado em 24/05/2020 - 02:09h

cviniciusaraujo escreveu:

msoliver escreveu:

cviniciusaraujo escreveu:

Pessoal, boa noite!

O código logo abaixo é um trecho editado de um projeto que eu estou desenvolvendo. Eu montei um "sisteminha" usando while e read para que cada caractere digitado pelo usuário seja verificado e que se caso for um caractere divergente do que é solicitado seja retornada uma mensagem de erro.

Como os caracteres são verificados um por vez, se eu colocar um break dentro do if abaixo de um else, o loop encerra e o valor da variável _USER será apenas o primeiro caractere digitado pelo usuário, sendo assim, não tem como o usuário terminar de digitar o que ele quer...

Alguém poderia me dá uma ajuda de como eu poderia finalizar o loop pressionando a tecla ENTER ou algo semelhante? Ou uma outra forma?


#!/bin/bash

clear
tput civis

while :; do
tput cup 1
read -p "Nome de usuário: " -n"$[${#_USER} + 1]" -e -i "$_USER" _USER
if echo "$_USER" | grep -q '[^a-z A-Z 0-9 ._-]'; then
tput cup 1 40
echo "Não foi possível criar o usuário!"
continue
fi
done

Boa noite cviniciusaraujo.
-n"$[${#_USER} + 1]"
Faz com que a variável "não tenha fim...."
Segue sugestão:
#!/bin/bash
clear
tput civis
while :; do Unset _USER;
tput cup 1
read -p "Nome de usuário: " -e -i "$_USER" _USER
if grep -q '[^a-z A-Z 0-9 ._-]' <<< "$_USER"; then
tput cup 1 40
echo "Não foi possível criar o usuário! $_USER"
else
echo "USER: $_USER OK"
tput reset
break;
fi
done



______________________________________________________________________
Importante: echo -e "\n$(lynx --dump goo.gl/a9KeFc|sed -nr '/^[ ]+Se/,/dou.$/p')\n"
Att.: Marcelo Oliver
______________________________________________________________________


Obrigado, Marcelo!

Sim, a variável "não tem fim", mas é necessária... Cada caractere digitado pelo usuário é lido e verificado em tempo real, ex:

Se o usuário digitar "exemplo#" imediatamente ele será notificado que o caractere "#" não é permitido e a pergunta é feita novamente junto com o que ele digitou. E isso sem a necessidade do usuário pressionar ENTER.

Estou procurando uma forma de encerar este loop quando o usuário pressionar ENTER...





4. Re: Interrompendo um loop while

mau blau
blaublau22

(usa GoblinX)

Enviado em 24/05/2020 - 19:02h

#!/bin/bash

#limpar a linha
clrline='\033[2K'

while true ; do

printf "\r${clrline}Nome de usuário: %s" "${_USER:-vazio}"

read -n 1

if [[ "$REPLY" = [^a-zA-Z0-9\ ._-] ]] ; then
printf "\r${clrline}Caráter ilegal -- %s" "$REPLY" >&2

unset REPLY
sleep 1
continue
elif [[ -z "$REPLY" ]]; then
break
else
_USER="$_USER$REPLY"
fi

done

echo "Nome final: $_USER"



não sei usar tput, mas usei no lugar, uma sequência par alimpar a linha, e também o '\r', para voltar no começo da linha.
por experiência, eles funcionam bem juntos com o printf..

o printf não interpreta como a gente quer o texto impresso, a não ser que seja explícito..

read com '-n 1', lê um caráter apenas

se entendi direito, o nome de usuário pode conter todos caráters, menos '[^a-z A-Z 0-9 ._-]'
porém isso está meio esquisito
é uma lista de exceções, você está repetindo o espaço em branco. eu escapei o espaço em branco com um '\', ok?! mas pode ser com o escape que vc colocou na expressão inteira

para que o usuário consiga deletar o último caráter, pode colocar o seguinte if no começo antes dos outros testes:

if [[ "$REPLY" = BACKSPACELITERAL ]]; then

_USER="${_USER:0:$(( ${#_USER} - 1 ))}"
continue
elif..


onde BACKSPACELITERAL deve ser um caráter de backspace literal gerado da seguinte forma:
no linux, vc deve apertar Ctrl+v e depois o backspace que ele vai gerar algo do tipo '^?'

se eu tentar te mandar ele, fica assim aqui no fórum --  (não dá para ver)

ou podemos pegar pesado e:
#!/bin/bash

#limpar a linha
clrline='\033[2K'

while true ; do

printf "\r${clrline}Nome de usuário: %s" "${_USER:-vazio}"

read -n 1

#checar por cód. backspace literal
codes=( $( od -An -t dC <<< "$REPLY" ) )
if [[ "${codes[0]}" = 127 ]]; then

#se estiver vazio, continue
(( ${#_USER} )) || continue

#se não, retire o último char
_USER="${_USER:0:$(( ${#_USER} - 1 ))}"
continue
#checar por char ilegais
elif [[ "$REPLY" = [^a-zA-Z0-9\ ._-] ]] ; then

printf "\r${clrline}Caráter ilegal -- %s" "$REPLY" >&2

unset REPLY
sleep 1
continue
#se deu um enter sem nada mais
elif [[ -z "$REPLY" ]]; then

break
#compor o nome de usuário
else

_USER="$_USER$REPLY"
fi

done

echo "Nome final: $_USER"



agora, se for só para sair do loop, uma vez que a conferência estiver correta, é só dar um ELSE e um BREAK


5. Re: Interrompendo um loop while [RESOLVIDO]

Carlos Vinícius
cviniciusaraujo

(usa Ubuntu)

Enviado em 24/05/2020 - 22:36h

blaublau22 escreveu:

#!/bin/bash

#limpar a linha
clrline='\033[2K'

while true ; do

printf "\r${clrline}Nome de usuário: %s" "${_USER:-vazio}"

read -n 1

if [[ "$REPLY" = [^a-zA-Z0-9\ ._-] ]] ; then
printf "\r${clrline}Caráter ilegal -- $REPLY" >&2

unset REPLY
sleep 1
continue
elif [[ -z "$REPLY" ]]; then
break
else
_USER="$_USER$REPLY"
fi

done

echo "Nome final: $_USER"



não sei usar tput, mas usei no lugar, uma sequência par alimpar a linha, e também o '\r', para voltar no começo da linha.
por experiência, eles funcionam bem juntos com o printf..

o printf não interpreta como a gente quer o texto impresso, a não ser que seja explícito..

read com '-n 1', lê um caráter apenas

se entendi direito, o nome de usuário pode ocnter todos caráters, menos '[^a-z A-Z 0-9 ._-]'
porém isso está meio esquisito
é uma lista de exceções, você está repetindo o espaço em branco. eu escapei o espaço em branco com um '\', ok?! mas pode ser com o escape que vc colocou na expressão inteira

para que o usuário consiga deletar o último caráter, pode colocar o seguinte if no começo antes dos outros testes:

if [[ "$REPLY" = BACKSPACELITERAL ]]; then

_USER="${_USER:0:$(( ${#_USER} - 1 ))}"
continue
elif..


onde BACKSPACELITERAL deve ser um caráter de backspace literal gerado da seguinte forma:
no linux, vc deve apertar Ctrl+v e depois o backspace que ele vai gerar algo do tipo '^?'

se eu tentar te mandar ele, fica assim aqui no fórum --  (não dá para ver)

ou podemos pegar pesado e:
#!/bin/bash

#limpar a linha
clrline='\033[2K'

while true ; do

printf "\r${clrline}Nome de usuário: %s" "${_USER:-vazio}"

read -n 1

#checar por cód. backspace literal
codes=( $( od -An -t dC <<< "$REPLY" ) )
if [[ "${codes[0]}" = 127 ]]; then

#se estiver vazio, continue
(( ${#_USER} )) || continue

#se não, retire o último char
_USER="${_USER:0:$(( ${#_USER} - 1 ))}"
continue
#checar por char ilegais
elif [[ "$REPLY" = [^a-zA-Z0-9\ ._-] ]] ; then

printf "\r${clrline}Caráter ilegal -- $REPLY" >&2

unset REPLY
sleep 1
continue
#se deu um enter sem nada mais
elif [[ -z "$REPLY" ]]; then

break
#compor o nome de usuário
else

_USER="$_USER$REPLY"
fi

done

echo "Nome final: $_USER"



agora, se for só para sair do loop, uma vez que a conferência estiver correta, é só dar um ELSE e um BREAK


Obrigado, blaublau22!

Isso é exatamente o que eu queria! Resolveu meu problema...






Patrocínio

Site hospedado pelo provedor RedeHost.
Linux banner

Destaques

Artigos

Dicas

Tópicos

Top 10 do mês

Scripts