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
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á siWORD=ca
oWORD=og
o similar y supongo que te refieres aecho ${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
.
shopt -s nocasematch
podría ayudar si desea que la búsqueda no distinga entre mayúsculas y minúsculas.[[
y]]
–[
y]
no son suficientes.[[ "$ARG" =~ ^(true|false)$ ]] || { echo "Argument received invalid value" ; exit 1 ; }
egrep -q "^$WORD$" /tmp/words; [[ $? != 0 ]] && echo "Not found" || echo "OK"
.