¿Existe un operador "in" en bash/bourne?

¿Existe un operador "in" en bash/bourne?

Estoy buscando un operador "in" que funcione así:

if [ "$1" in ("cat","dog","mouse") ]; then
    echo "dollar 1 is either a cat or a dog or a mouse"
fi

Obviamente es una declaración mucho más corta en comparación con, digamos, el uso de varias pruebas "o".

Respuesta1

Puedes usar case...esac

$ cat in.sh 
#!/bin/bash

case "$1" in 
  "cat"|"dog"|"mouse")
    echo "dollar 1 is either a cat or a dog or a mouse"
  ;;
  *)
    echo "none of the above"
  ;;
esac

Ex.

$ ./in.sh dog
dollar 1 is either a cat or a dog or a mouse
$ ./in.sh hamster
none of the above

Con ksh, bash -O extglobo zsh -o kshglob, también puedes usar un patrón global extendido:

if [[ "$1" = @(cat|dog|mouse) ]]; then
  echo "dollar 1 is either a cat or a dog or a mouse"
else
  echo "none of the above"
fi

Con bash, ksh93o zsh, también puedes usar una comparación de expresiones regulares:

if [[ "$1" =~ ^(cat|dog|mouse)$ ]]; then
  echo "dollar 1 is either a cat or a dog or a mouse"
else
  echo "none of the above"
fi

Respuesta2

No hay una prueba "in" en bash, pero sí una prueba de expresiones regulares (no en bourne):

if [[ $1 =~ ^(cat|dog|mouse)$ ]]; then
    echo "dollar 1 is either a cat or a dog or a mouse"
fi

Y generalmente escrito usando una variable (menos problemas con las comillas):

regex='^(cat|dog|mouse)$'

if [[ $1 =~ $regex ]]; then
    echo "dollar 1 is either a cat or a dog or a mouse"
fi

Para un shell Bourne más antiguo necesitas usar una coincidencia de casos:

case $1 in
    cat|dog|mouse)   echo "dollar 1 is either a cat or a dog or a mouse";;
esac

Respuesta3

Usar a caseestá bien si tienes un conjunto fijo de mascotas con las que quieres comparar. Pero no funcionará si necesita crear el patrón en tiempo de ejecución, ya que caseno interpreta la alternancia dentro de los parámetros expandidos.

Esto coincidirá sólo con la cadena literal cat|dog|mouse:

patt='cat|dog|mouse'
case $1 in 
        $patt) echo "$1 matches the case" ;; 
esac

Sin embargo, puedes utilizar una variable con la coincidencia de expresión regular. Siempre que la variable no esté entre comillas, cualquier operador de expresiones regulares que contenga tiene significados especiales.

patt='cat|dog|mouse'
if [[ "$1" =~ ^($patt)$ ]]; then
        echo "$1 matches the pattern"
fi

También puedes usar matrices asociativas. Comprobar si existe una clave en uno es lo más parecido a un inoperador que ofrece Bash. Aunque la sintaxis es un poco fea:

declare -A arr
arr[cat]=1
arr[dog]=1
arr[mouse]=1

if [ "${arr[$1]+x}" ]; then
        echo "$1 is in the array"
fi

(${arr[$1]+x}se expande xsi arr[$1]está configurado; en caso contrario, se vacía.)

Respuesta4

grepacercarse.

if echo $1 | grep -qE "^(cat|dog|mouse)$"; then 
    echo "dollar 1 is either a cat or a dog or a mouse"
fi
  • -qpara evitar cualquier salida a la pantalla (es más rápido de escribir que >/dev/null).
  • -Epara aspectos de expresiones regulares extendidas (cat|dog|mouse)se necesita esto.
  • ^(cat|dog|mouse)$coincide con cualquier línea que comience ( ^) con gato, perro o ratón ( (cat|dog|mouse)) seguido del final de la línea ( $)

información relacionada