bash: prueba si $ WORD está en el conjunto

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

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

¿tiene bash tal construcción? Si no es así, ¿cuál sería la más cercana?

Respuesta

Esta es una solución 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 se puede remediar con algo como:

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

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

Comentarios

  • Y shopt -s nocasematch podría ayudar si desea que la búsqueda no distinga entre mayúsculas y minúsculas.
  • Tenga en cuenta que debe usar [[ y ]][ y ] no son suficientes.
  • Estaba buscando para un ‘ oneliner ‘ para validar mi argumento de script, y esto funcionó perfectamente. ¡gracias! [[ "$ARG" =~ ^(true|false)$ ]] || { echo "Argument received invalid value" ; exit 1 ; }
  • Si ‘ va a poner su lista de coincidencias en un archivo, también puede usar grep: egrep -q "^$WORD$" /tmp/words; [[ $? != 0 ]] && echo "Not found" || echo "OK".

Respuesta

case $word in dog|cat|horse) echo yes;; *) echo no;; esac 

Respuesta

¿Qué tal:

#!/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" 

Luego:

$ a.sh cat cat is in the list $ a.sh bob bob is not in the list 

Responder

if (echo "$set" | fgrep -q "$WORD") 

Comentarios

  • Sin embargo, tenga cuidado, esto devolverá verdadero si $WORD está vacío, coincidirá si WORD=ca o WORD=og o similar y supongo que te refieres a echo ${set[@]}.
  • solo agrega -w a grep para evitar palabras parciales

Respuesta

Puede 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 

Respuesta

Estaba buscando una solución de «una línea» para validar el argumento de mi script, y usé Joseph R. answer más arriba. con:

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

Responder

Usted podría 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 bandera -w solo coincide con palabras completas, la -q la marca hace que funcione de forma silenciosa (porque todo lo que necesitamos es el valor de retorno de la instrucción if a utilizar), y cada -e patrón especifica un patrón para permitir.

fgrep es la versión de grep que hace una coincidencia de cadenas normal en lugar de una coincidencia de expresiones regulares. Si tiene grep, debe tener fgrep, pero si no, es idéntico a usar grep con el indicador -F (por lo que simplemente reemplazaría fgrep -wq arriba con grep -Fwq).

Respuesta

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 

Responder

Es posible que desee poner la lista de palabras en un archivo, en caso de que cambie la lista con frecuencia, o si lo desea ser compartido por varios scripts. Y es posible que deba poner las palabras en un archivo si la lista es demasiado larga para administrar en un script. Entonces puede decir

if fgrep –qx "$WORD" word_list 

Comentarios

  • no, no ‘ no quiero tener mi lista en un archivo

Responder

Si las palabras son una lista en la que 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 

Respuesta

Acabo de tener el mismo problema y encontré una solución sorprendentemente comprensible que no requiere ningún conocimiento de expresiones regulares.

Tenga en cuenta que el La solución que se muestra a continuación puede ser solo de bash, porque no tengo ni idea de las diferencias entre bash y otras shells. Además, el manual de bash advierte que este tipo de coincidencia de patrones es lento si la cadena que debe coincidir es larga.

WORD=abc [[ "$WORD" == @(def|abc|ghi|foo|barbaz) ]] && echo Word is in set. 

¿Cómo funciona?No quiero repetir grandes porciones del manual de bash aquí, pero en mis propias palabras:

Si el operador binario == se usa con el comando compuesto [[, la palabra del lado derecho del operador experimenta una coincidencia de patrones como se explica en la sección » Coincidencia de patrones » en el manual de bash. Además, en estas condiciones, mientras coincide, se supone que la opción de shell extglob está configurada (independientemente de la configuración real); esto es el punto clave para entender lo anterior.

Pero, ¿qué pasa si las palabras en su conjunto ya contienen caracteres que tienen un significado especial en la coincidencia de patrones, sustitución de comandos y otras expansiones? El remedio es fácil: simplemente use algo como

[[ "$WORD" == @("a*"|abc|"?ghi"|"$DontExpandMe"|barbaz) ]] && echo Word is in set. 

Me pareció muy fácil, comprensible y eficiente (siempre que $WORD sea corto) solución que no tiene efectos secundarios o se da ngerous como los métodos basados en set.

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *