script bash para comprobar si la entrada tiene @

script bash para comprobar si la entrada tiene @

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 externogreputilidad:

#!/usr/bin/env bash

read -erp '> '
if grep -q @ <<<"$REPLY"; then
    echo pass
else
    echo fail
fi

Pasar la -qbandera grepevita 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 ifconstrucció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 passse suponía que debía imprimirse y echono se pudo imprimir. Entonces, presumiblemente, el eco tampoco se imprimiría fail.
  • Si bien los cortocircuitos &&y ||a menudo son apropiados en sí mismos (y los uso con frecuencia para abreviar unif sinuna elseclá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:

  • -ehabilita 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, readcoloca automáticamente la entrada del usuario en la REPLYvariable si no se proporcionó ninguna variable.
  • Aaquí cadenawith <<<es una manera conveniente de pasar la entrada del usuario a grep.
  • 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, -ptiene un significado diferente.
    (Gracias ageirhapor señalar tanto que-pa 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 conheaden lugar de read:

#!/bin/sh

printf '> '
if head -1 | grep -q @; then
    echo pass
else
    echo fail
fi

Comogeirha mencionó, head -n 1podría considerarse una mejor sintaxis tal como head -1estáoficialmente obsoleto(aunque las implementaciones actuales sed, o al menos GNU sed, son compatibles -1con sus últimas versiones, mientras que algunas sedimplementaciones muy antiguas no son compatibles -n 1).

Comola headdocumentacióndice, puedes usarlo seden 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 bashcó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 $varno 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 de patternin varcon string. En nuestro caso, patternes [^@]cual es una expresión regular que coincide con cada carácter.excepto @. Por lo tanto, ${var//[^@]/}devuelve una cadena vacía a menos que varcontenga 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 si varcontiene 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 -popción deread. Entonces, en su lugar se usa una combinación de printfy . readAdemás, al carecer de las funciones avanzadas de expansión de variables de bash, la casedeclaració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 shscripts puedes usar caseen 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 dashshell:

$ 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
$ 

información relacionada