bash: prueba si $ WORD está en conjunto

54

Estoy buscando una construcción en bash, para decidir si una variable $WORDes una de las palabras definidas. Necesito algo como esto:

if "$WORD" in dog cat horse ; then 
    echo yes
else
    echo no
fi

¿bash tiene tal construcción? Si no, ¿cuál sería el más cercano?

Martin Vegter
fuente

Respuestas:

57

Esta es una solución de solo Bash (> = versión 3) que usa expresiones regulares:

if [[ "$WORD" =~ ^(cat|dog|horse)$ ]]; then
    echo "$WORD is in the list"
else
    echo "$WORD is not in the list"
fi

Si su lista de palabras es larga, puede almacenarla en un archivo (una palabra por línea) y hacer esto:

if [[ "$WORD" =~ $(echo ^\($(paste -sd'|' /your/file)\)$) ]]; then
    echo "$WORD is in the list"
else
    echo "$WORD is not in the list"
fi

Una advertencia con el enfoque de archivo:

  • Se romperá si el archivo tiene espacios en blanco. Esto puede remediarse mediante algo como:

    sed 's/[[:blank:]]//g' /your/file | paste -sd '|' /dev/stdin

Gracias a @terdon por recordarme que ancle correctamente el patrón con ^y $.

Joseph R.
fuente
1
Y shopt -s nocasematchpodría ayudar si desea que la búsqueda no distinga entre mayúsculas y minúsculas.
Skippy le Grand Gourou
1
Tenga en cuenta que debe usar [[y ]], [y ]no son suficientes.
Greg Dubicki
Estaba buscando un 'oneliner' para validar mi argumento de script, y esto funcionó perfectamente. ¡gracias! [[ "$ARG" =~ ^(true|false)$ ]] || { echo "Argument received invalid value" ; exit 1 ; }
RASG
76
case $word in
    dog|cat|horse) echo yes;;
    *)             echo no;;
esac
John Kugelman apoya a Monica
fuente
11

Qué tal si:

#!/usr/bin/env bash

WORD="$1"
for w in dog cat horse
do
  if [ "$w" == "$WORD" ] 
  then
      yes=1
      break
  fi
done;
[ "$yes" == "1" ] && echo "$WORD is in the list" || 
                     echo "$WORD is not in the list"

Entonces:

$ a.sh cat
cat is in the list
$ a.sh bob
bob is not in the list
terdon
fuente
3
if (echo "$set"  | fgrep -q "$WORD")
BrenoZan
fuente
1
Aunque cuidado, esto devolverá verdadero si $WORDestá vacío, que coincidirá si WORD=cao WORD=ogo similar y supongo que quería decir echo ${set[@]}.
terdon
simplemente agregue -w a grep para evitar palabras parciales
BrenoZan
1

Podría definir una función bash para esto:

function word_valid() 
{ 
  if [ "$1" != "cat" -a "$1" != "dog" -a "$1" != "horse" ];then
    echo no
  else
    echo yes
  fi
}

Luego use simplemente así:

word_valid cat
sospechoso
fuente
1

Estaba buscando una solución de 'una línea' para validar mi argumento de script, y utilicé la respuesta de Joseph R. anterior para llegar a:

[[ "$ARG" =~ ^(true|false)$ ]] || { echo "Argument received invalid value" ; exit 1 ; }

RASG
fuente
0

Esto funcionó para mí:

#!/bin/bash
phrase=(cat dog parrot cow horse)
findthis=parrot

for item in ${phrase[*]}
do
    test "$item" == "$findthis" && { echo "$findthis found!"; break; }
done
Javier
fuente
0

Es posible que desee colocar la lista de palabras en un archivo, en caso de que cambie la lista con frecuencia, o si desea que varias secuencias de comandos la compartan. Y es posible que deba poner las palabras en un archivo si la lista se vuelve demasiado larga para administrarla en un script. Entonces puedes decir

if fgrep qx "$WORD" word_list
Scott
fuente
no, no quiero tener mi lista en un archivo
Martin Vegter
0

Si las palabras son una lista donde los valores están separados por una nueva línea, puede hacer:

WORDS="$(ls -1)"
if echo "${WORDS}" | grep --quiet --line-regexp --fixed-strings "${WORD}"; then
    echo yes
else
    echo no
fi
Mitar
fuente
0

Puede usar fgrep para especificar todas las palabras permitidas:

if $(echo "$WORD" | fgrep -wq -e dog -e cat -e horse) ; then 
    echo yes
else
    echo no
fi

La -wbandera solo coincide con palabras completas, la -qbandera hace que opere en silencio (porque todo lo que necesitamos es el valor de retorno de la instrucción if para usar), y cada -epatrón especifica un patrón para permitir.

fgrepes la versión de grep que hace una coincidencia normal de cadenas en lugar de una coincidencia de expresiones regulares. Si es así grep, debería serlo fgrep, pero si no, es idéntico al uso grepcon la -Fbandera (por lo que simplemente reemplazaría el fgrep -wqanterior con grep -Fwq).

Christopher Shroba
fuente