![script bash para comprobar si la entrada tiene @](https://rvso.com/image/1048309/script%20bash%20para%20comprobar%20si%20la%20entrada%20tiene%20%40.png)
Hola, estoy intentando escribir un script bash en el que se verifica la entrada para ver si contiene un símbolo @. Soy relativamente nuevo en bash, ¡así que perdone todos los errores! Hasta ahora tengo:
var1="@"
var2="INPUT"
echo "input"
read INPUT
if [[ "$var2" == "$var1" ]]; then
echo "pass"
else
echo "fail"
fi
Respuesta1
Aunque tiene la opción de usar la funcionalidad de shell incorporada para verificar si la entrada del usuario está contenida @
(lo cual está bien documentado en las otras respuestas), otra forma razonable de hacerlo es con el externogrep
utilidad:
#!/usr/bin/env bash
read -erp '> '
if grep -q @ <<<"$REPLY"; then
echo pass
else
echo fail
fi
Pasar la -q
bandera grep
evita que imprima líneas coincidentes. (También evita que lea más líneas después de encontrar una coincidencia, pero eso no hace ninguna diferencia aquí ya que solo hay una línea de entrada).
Es tentador acortar la if
construcción a algo como grep -q @ <<<"$REPLY" && echo pass || echo fail
, pero he evitado hacerlo deliberadamente:
- En este caso, probablemente esté bien, ya que la única forma en que se imprime la palabra incorrecta es si
pass
se suponía que debía imprimirse yecho
no se pudo imprimir. Entonces, presumiblemente, el eco tampoco se imprimiríafail
. - Si bien los cortocircuitos
&&
y||
a menudo son apropiados en sí mismos (y los uso con frecuencia para abreviar unif
sinunaelse
cláusula), usándolos juntos como si fueranun ternariosioperadorNo es realmente un buen hábito. Si bien algunos comandos no puedenfallar,echo
poder. - Si el usuarioredireccionesla salida de su secuencia de comandos a un archivo o dispositivo no grabable, o lo usa en un archivo rototubería, echo y otros comandos que generan texto pueden devolver un error, lo que hace que la
&&
expresión falle y||
se ejecute el lado derecho de la expresión. - Puede probar el comportamiento de un script en presencia de un dispositivo de salida no grabable ejecutándolo con
>/dev/full
.
Ese script utiliza algunas características de bash:
-e
habilita GNU readline, por lo que el usuario puede mover el cursor hacia la izquierda y hacia la derecha con las teclas de flecha para editar su entrada mientras la ingresa.- En bash,
read
coloca automáticamente la entrada del usuario en laREPLY
variable si no se proporcionó ninguna variable. - Aaquí cadenawith
<<<
es una manera conveniente de pasar la entrada del usuario agrep
. - golpe yalgunoSe aceptan otros shells estilo Bourne, como Dash
-p
. PeroLos shells compatibles con POSIX sólo necesitan comprender-r
. Y en algunos, como ksh,-p
tiene un significado diferente.
(Gracias ageirhapor señalar tanto que-p
a veces esta ausentey esono siempre significa "rápido".)
Si desea un script que sea portátil para otros sistemas operativos que quizás no tengan instalado bash, puede usar:
#!/bin/sh
printf '> '
read -r line
if printf '%s' "$line" | grep -q @; then
echo pass
else
echo fail
fi
Si lo desea, puede omitir el almacenamiento de la entrada del usuario en una variable leyéndola conhead
en lugar de read
:
#!/bin/sh
printf '> '
if head -1 | grep -q @; then
echo pass
else
echo fail
fi
Comogeirha mencionó, head -n 1
podría considerarse una mejor sintaxis tal como head -1
estáoficialmente obsoleto(aunque las implementaciones actuales sed
, o al menos GNU sed, son compatibles -1
con sus últimas versiones, mientras que algunas sed
implementaciones muy antiguas no son compatibles -n 1
).
Comola head
documentacióndice, puedes usarlo sed
en su lugar para obtener la máxima portabilidad.
#!/bin/sh
printf '> '
if sed 1q | grep -q @; then
echo pass
else
echo fail
fi
Respuesta2
Este bash
código lee la entrada y señala "Aprobado" si la entrada contiene un @
símbolo:
read -p "Input: " var
[ "${var//[^@]/}" ] && echo Pass || echo Fail
Notas:
[ "$var" ]
es una prueba de bash. Devuelve verdadero si la cadena$var
no está vacía.Una de las características de bash es la sustitución de patrones. Parece que
${var//pattern/string}
. Reemplaza cada aparición depattern
invar
constring
. En nuestro caso,pattern
es[^@]
cual es una expresión regular que coincide con cada carácter.excepto@
. Por lo tanto,${var//[^@]/}
devuelve una cadena vacía a menos quevar
contenga al menos un archivo@
.Combinamos los dos anteriores:
[ "${var//[^@]/}" ]
Esta prueba solo tiene éxito si
${var//[^@]/}
no está vacía y${var//[^@]/}
no está vacía solo sivar
contiene al menos un archivo@
.
Usando un if-then-else explícito:
read -p "Input: " var
if [ "${var//[^@]/}" ]
then
echo Pass
else
echo Fail
fi
Carcasa POSIX
Lo siguiente funciona bajo dash
( /bin/sh
) y debería funcionar bajo cualquier shell POSIX:
printf "Input: "
read var
case "$var" in
*@*) echo Pass
;;
*) echo Fail
;;
esac
El shell POSIX no admite la -p
opción deread
. Entonces, en su lugar se usa una combinación de printf
y . read
Además, al carecer de las funciones avanzadas de expansión de variables de bash
, la case
declaración se puede utilizar para coincidencias globales.
Carcasa de Android
Usando el shell predeterminado en mi Android, funciona lo siguiente:
echo -n "Input: "; read var
if ! [ "${var//@/}" = "$var" ]
then
echo Pass
else
echo Fail
Respuesta3
La forma preferida en bash es utilizar la función de coincidencia de patrones de [[ ... ]]
.
#bash
read -rp "Input: " input
if [[ $input = *@* ]]; then
printf '<%s> contains @\n' "$input"
fi
Para sh
scripts puedes usar case
en su lugar.
#sh
printf 'Input: '
read -r input
case $input in
*@*) printf '<%s> contains @\n' "$input" ;;
esac
Ver también elPruebas y condicionalescapítulo de la Guía Bash.
Respuesta4
En versiones más nuevas de bash, debería poder utilizar uncoincidencia de expresiones regularesa través del =~
operador de prueba extendido:
$ 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
Una alternativa que debería funcionar en cualquier sistema compatible con POSIX es utilizar expr
, por ejemplo, en el 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
$