bash: teste se $ WORD está definido

54

Estou procurando uma construção bash, para decidir se uma variável $WORDé uma das palavras definidas. Eu preciso de algo assim:

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

bash tem essa construção? Caso contrário, qual seria o mais próximo?

Martin Vegter
fonte

Respostas:

57

Esta é uma solução somente Bash (> = versão 3) que usa expressões regulares:

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

Se sua lista de palavras for longa, você pode armazená-la em um arquivo (uma palavra por linha) e fazer o seguinte:

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

Uma ressalva com a abordagem de arquivo:

  • Ele será interrompido se o arquivo tiver espaço em branco. Isso pode ser remediado por algo como:

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

Agradeço ao @terdon por me lembrar de ancorar adequadamente o padrão com ^e $.

Joseph R.
fonte
11
E shopt -s nocasematchpode ajudar se você desejar que a pesquisa não diferencie maiúsculas de minúsculas.
Skippy le Grand Gourou
11
Observe que você precisa usar [[e ]]- [e ]não é suficiente.
precisa saber é o seguinte
Eu estava procurando por um 'oneliner' para validar meu argumento de script, e isso funcionou perfeitamente. obrigado! [[ "$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 apoia Monica
fonte
11

E se:

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

Então:

$ a.sh cat
cat is in the list
$ a.sh bob
bob is not in the list
terdon
fonte
3
if (echo "$set"  | fgrep -q "$WORD")
BrenoZan
fonte
11
Cuidado, porém, isso retornará verdadeiro se $WORDestiver vazio, corresponderá se WORD=caou WORD=ogou semelhante e suponho que você quis dizer echo ${set[@]}.
terdon
basta adicionar -w ao grep para evitar palavras parciais
BrenoZan
1

Você pode definir uma função bash para isso:

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

Então use simplesmente assim:

word_valid cat
suspeito
fonte
1

Eu estava procurando por uma solução 'de uma linha' para validar meu argumento de script e usei a resposta de Joseph R. acima para criar:

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

RASG
fonte
0

Isso funcionou para mim:

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

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

Você pode colocar a lista de palavras em um arquivo, caso mude a lista com frequência ou queira que ela seja compartilhada por vários scripts. E pode ser necessário colocar as palavras em um arquivo se a lista demorar muito para ser gerenciada em um script. Então você pode dizer

if fgrep qx "$WORD" word_list
Scott
fonte
não, não quero ter minha lista em um arquivo
Martin Vegter
0

Se as palavras são uma lista em que os valores são separados por uma nova linha, você pode:

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

Você pode usar o fgrep para especificar todas as palavras permitidas:

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

O -wsinalizador corresponde apenas a palavras completas, o -qsinalizador faz com que ele funcione silenciosamente (porque tudo o que precisamos é o valor de retorno para a instrução if usar), e cada -epadrão especifica um padrão a ser permitido.

fgrepé a versão do grep que faz a correspondência normal de cadeias de caracteres em vez da correspondência de regex. Se você tiver grep, você deve ter fgrep, mas se não, é idêntico ao uso grepcom a -Fbandeira (então você substitui fgrep -wqacima por grep -Fwq).

Christopher Shroba
fonte