![script bash para verificar se a entrada tem um @](https://rvso.com/image/1048309/script%20bash%20para%20verificar%20se%20a%20entrada%20tem%20um%20%40.png)
Olá, estou tentando escrever um script bash no qual a entrada é verificada para ver se contém um símbolo @. Sou relativamente novo no bash, então perdoe todos/todos os erros! Até agora eu tenho:
var1="@"
var2="INPUT"
echo "input"
read INPUT
if [[ "$var2" == "$var1" ]]; then
echo "pass"
else
echo "fail"
fi
Responder1
Embora você tenha a opção de usar a funcionalidade interna do shell para verificar se a entrada do usuário está contida @
(o que está bem documentado nas outras respostas), outra maneira razoável de fazer isso é com o externogrep
Utilitário:
#!/usr/bin/env bash
read -erp '> '
if grep -q @ <<<"$REPLY"; then
echo pass
else
echo fail
fi
Passar o -q
sinalizador para grep
evita a impressão de linhas correspondentes. (Também evita que ele leia mais linhas depois de encontrar uma correspondência, mas isso não faz diferença aqui, pois há apenas uma linha de entrada.)
É tentador encurtar a if
construção para algo como grep -q @ <<<"$REPLY" && echo pass || echo fail
, mas evitei deliberadamente fazer isso:
- Nesse caso, provavelmente está tudo bem, já que a única maneira de a palavra errada ser impressa é se
pass
deveria ser impressa eecho
não foi impressa. Então, presumivelmente, echofail
também não seria impresso . - Embora curto-circuito
&&
e||
muitas vezes sejam apropriados (e eu os uso frequentemente para abreviar umif
semumaelse
cláusula), usando-os juntos como se fossemum ternárioseoperadornão é realmente um bom hábito. Embora alguns comandos não possamfalhar,echo
pode. - Se o usuárioredirecionamentosa saída do seu script para um arquivo ou dispositivo não gravável, ou usa-o de forma quebradagasoduto, echo e outros comandos que geram texto podem retornar falha, fazendo com que a
&&
expressão falhe e o lado direito da||
expressão seja executado. - Você pode testar o comportamento de um script na presença de um dispositivo de saída não gravável executando-o com
>/dev/full
.
Esse script usa alguns recursos do bash:
-e
habilita o readline GNU, para que o usuário possa mover o cursor para a esquerda e para a direita com as teclas de seta para editar sua entrada ao inseri-la.- No bash,
read
coloca automaticamente a entrada do usuário naREPLY
variável se nenhuma variável for fornecida. - Aaqui stringwith
<<<
é uma maneira conveniente de passar a entrada do usuário paragrep
. - Bash ealgunsoutros shells no estilo Bourne, como dash, aceitam
-p
. MasShells compatíveis com POSIX precisam apenas entender-r
. E em alguns, como ksh,-p
tem um significado diferente.
(Graças ageirhapor apontar tanto isso-p
às vezes está ausentee essanem sempre significa "rápido".)
Se você deseja um script portátil para outros sistemas operacionais que talvez não tenham o bash instalado, você pode usar:
#!/bin/sh
printf '> '
read -r line
if printf '%s' "$line" | grep -q @; then
echo pass
else
echo fail
fi
Se desejar, você pode pular o armazenamento da entrada do usuário em uma variável lendo-a comhead
em vez de read
:
#!/bin/sh
printf '> '
if head -1 | grep -q @; then
echo pass
else
echo fail
fi
ComoGeirha mencionou, head -n 1
pode ser considerada uma sintaxe melhor como head -1
éoficialmente obsoleto(embora as implementações atuais sed
, ou pelo menos o GNU sed, suportem -1
suas versões mais recentes, enquanto algumas sed
implementações muito antigas não suportam -n 1
).
Comoa head
documentaçãodiz, você pode usar sed
em vez disso para máxima portabilidade.
#!/bin/sh
printf '> '
if sed 1q | grep -q @; then
echo pass
else
echo fail
fi
Responder2
Este bash
código lê a entrada e sinaliza "Aprovado" se a entrada contiver um @
símbolo:
read -p "Input: " var
[ "${var//[^@]/}" ] && echo Pass || echo Fail
Notas:
[ "$var" ]
é um teste bash. Ele retorna verdadeiro se a string$var
não estiver vazia.Um dos recursos do bash é a substituição de padrões. Parece
${var//pattern/string}
. Ele substitui todas as ocorrências depattern
invar
porstring
. No nosso caso,pattern
é[^@]
uma expressão regular que corresponde a todos os caracteresexceto@
. Assim,${var//[^@]/}
retorna uma string vazia, a menos quevar
contenha pelo menos um@
.Combinamos os dois acima:
[ "${var//[^@]/}" ]
Este teste será bem-sucedido somente se
${var//[^@]/}
não estiver vazio e${var//[^@]/}
não estiver vazio somente sevar
contiver pelo menos um@
.
Usando um if-then-else explícito:
read -p "Input: " var
if [ "${var//[^@]/}" ]
then
echo Pass
else
echo Fail
fi
Concha POSIX
O seguinte funciona em dash
( /bin/sh
) e deve funcionar em qualquer shell POSIX:
printf "Input: "
read var
case "$var" in
*@*) echo Pass
;;
*) echo Fail
;;
esac
O shell POSIX não suporta a -p
opção deread
. Portanto, uma combinação de printf
e read
é usada. Além disso, na falta de recursos avançados de expansão de variáveis bash
, a case
instrução pode ser usada para correspondência glob.
Concha Android
Usando o shell padrão no meu Android, funciona o seguinte:
echo -n "Input: "; read var
if ! [ "${var//@/}" = "$var" ]
then
echo Pass
else
echo Fail
Responder3
A maneira preferida no bash é usar o recurso de correspondência de padrões do [[ ... ]]
.
#bash
read -rp "Input: " input
if [[ $input = *@* ]]; then
printf '<%s> contains @\n' "$input"
fi
Para sh
scripts, você pode usar case
.
#sh
printf 'Input: '
read -r input
case $input in
*@*) printf '<%s> contains @\n' "$input" ;;
esac
Veja também oTestes e Condicionaiscapítulo do Guia Bash.
Responder4
Nas versões mais recentes do bash, você poderá usar umcorrespondência de expressão regularatravés do =~
operador de teste estendido:
$ read -p "input: " input
input: quertyuiop
$ if [[ $input =~ \@ ]]; then echo "match"; else echo "no match"; fi
no match
$
$ read -p "input: " input
input: qwerty@uiop
$ if [[ $input =~ \@ ]]; then echo "match"; else echo "no match"; fi
match
Uma alternativa que deve funcionar em qualquer sistema compatível com POSIX é usar, expr
por exemplo, no dash
shell:
$ read input
qwertyuiop
$ if expr "$input" : '.*@.*' > /dev/null; then echo 'match'; else echo 'no match'; fi
no match
$
$ read input
qwerty@uiop
$ if expr "$input" : '.*@.*' > /dev/null; then echo 'match'; else echo 'no match'; fi
match
$