Como eu verifico se um determinado parâmetro está em uma determinada matriz?

1

Eu tenho um script de shell script.sh assim:

names=( jack john jerry)

E eu quero que o usuário digite qualquer um desses três nomes como seu primeiro parâmetro, assim como:

./script.sh jack

Se o usuário digitou um errado, por exemplo

./script.sh kate

Ele acionará um exit e pedirá ao usuário que digite apenas um desses 3.

O que devo fazer?

    
por AGamePlayer 04.09.2015 / 16:22

3 respostas

4

names=(jack john jerry); 
if [[ " "${names[@]}" " == *" "$1" "* ]] ;then 
    echo "$1: ok"
else 
    echo "$1: not recognized. Valid names are:"
    echo "${names[@]/%/,}"
    exit 1
fi

O código acima funciona para nomes que não contêm espaço em branco.
A versão modificada, abaixo, pode manipular espaços em branco em nomes.

names=("flash jack" john jerry); 
d=$''   # validation delimiter - value is \x01
valid="${names[@]/%/$d}"
valid="$d${valid//$d /$d}"
if [[ $valid == *$d$1$d* ]] ;then 
    echo "$1: ok"
else 
    echo "$1: not recognized. Valid names are:"
    echo "${names[@]/%/,}"
    exit 1
fi

Saída para versão com espaço em branco:

flash jack: ok

ou

kate: not recognized. Valid names are:
flash jack, john, jerry,
    
por 04.09.2015 / 16:37
0

É precisamente para isso que as declarações case são para:

#! /bin/bash

case $1 in
    [Jj]ack)
        echo "You chose Jack!"
    ;;
    [Jj]ohn)
        echo "You chose John!"
    ;;
    [Jj]erry)
        echo "You chose Jerry!"
    ;;
    ## For all other cases
    *)
        echo 'Please choose one of "John", "Jack" or "Jerry"' >&2
    exit 1
esac

A instrução case será executada no valor de $1 , o primeiro parâmetro que você passa para o seu script. Se for jack ou Jack , a primeira opção será executada, se for John ou john a segunda, etc. Se mais alguma coisa for inserida, a última instrução será executada.

    
por 04.09.2015 / 17:21
-1
Em primeiro lugar, eu preciso mencionar que scripts de shell substanciais o suficiente para usar a implementação de array horrível provavelmente serão considerados como o spawn do diabo. Além disso, você não indicou qual shell, mas estou assumindo o bash.

Existem muitas maneiras de fazer isso, tudo feio.

1) Iterar sobre o array. É legível e relativamente limpo, mas ineficiente.

for i in 0 1 2 3 4
do
echo compare ${ARRAY[$i]} perhaps using test or whatever you like
done

2) Use expr para fazer tudo de uma vez. Isso é frágil e irá quebrar se um nome for uma subcadeia de outro. Isso pode ser corrigido, mas eu recomendaria o uso de uma ferramenta melhor se fosse possível

$ ARRAY=(jack john jerry )
$ expr "${ARRAY[*]}" : '.*jack.*'
15  # it's found
$ expr "${ARRAY[*]}" : '.*sue.*'
0   # not found

Onde jack ou sue são substituídos por $ 1 ou qualquer arg que você queira verificar.

    
por 04.09.2015 / 16:42

Tags