Por que você não usa o caso?
case $text in
us-east-1|us-west-2|us-west-1|eu-central-1|ap-southeast-1|etc)
echo "Working"
;;
*)
echo "Invalid option: $text"
;;
esac
Estou tentando ativar apenas algumas opções ao usar o comando read
e sair do script se uma possibilidade errada foi inserida.
Tentei muitas possibilidades (matriz, variáveis, alteração de sintaxe), mas ainda estou preso ao meu problema inicial.
Como faço para testar a entrada do usuário e permitir \ não permitir que o restante do script seja executado?
#!/bin/bash
red=$(tput setaf 1)
textreset=$(tput sgr0)
echo -n 'Please enter requested region > '
echo 'us-east-1, us-west-2, us-west-1, eu-central-1, ap-southeast-1, ap-northeast-1, ap-southeast-2, ap-northeast-2, ap-south-1, sa-east-1'
read text
if [ -n $text ] && [ "$text" != 'us-east-1' -o us-west-2 -o us-west-1 -o eu-central-1 -o ap-southeast-1 -o ap-northeast-1 -o ap-southeast-2 -o ap-northeast-2 -o ap-south-1 -o sa-east-1 ] ; then
echo 'Please enter the region name in its correct form, as describe above'
else
echo "you have chosen ${red} $text ${textreset} region."
AWS_REGION=$text
echo $AWS_REGION
fi
Por que não facilitar um pouco a vida do usuário ao não exigir que eles digam o nome da região?
#!/bin/bash
echo "Select region"
PS3="region (1-10): "
select region in "us-east-1" "us-west-2" "us-west-1" "eu-central-1" \
"ap-southeast-1" "ap-northeast-1" "ap-southeast-2" \
"ap-northeast-2" "ap-south-1" "sa-east-1"
do
if [[ -z $region ]]; then
echo "Invalid choice: '$REPLY'" >&2
else
break
fi
done
echo "You have chosen the '$region' region"
Se o usuário digitar algo diferente de uma opção numérica válida da lista, o valor em $region
será uma string vazia e exibiremos uma mensagem de erro. Se a escolha for válida, o loop sai.
Executando:
$ bash script.sh
Select region
1) us-east-1 4) eu-central-1 7) ap-southeast-2 10) sa-east-1
2) us-west-2 5) ap-southeast-1 8) ap-northeast-2
3) us-west-1 6) ap-northeast-1 9) ap-south-1
region (1-10): aoeu
Invalid choice: 'aoeu'
region (1-10): .
Invalid choice: '.'
region (1-10): -1
Invalid choice: '-1'
region (1-10): 0
Invalid choice: '0'
region (1-10): '
Invalid choice: '''
region (1-10): 5
You have chosen the 'ap-southeast-1' region
O problema é com isto:
[ "$text" != 'us-east-1' -o us-west-2 -o ... ]
O -o
significa ou e você precisa de uma condição completa, por isso seria
[ "$text" != 'us-east-1' -o "$text" != 'us-west-2' -o ... ]
Veja como estamos tendo que testar $text
a cada vez?
Sua lógica também está errada; você quer -a
( e ); se não for "us-east-1" e não é "us-west-2" e não é ...
Então
[ "$text" != 'us-east-1' -a "$text" != 'us-west-2' -a ... ]
Existem outras maneiras de fazer esse tipo de teste; alguns dos quais são meramente "preferência pessoal". No entanto, esta sintaxe deve levá-lo e segue a forma e estrutura do seu original.
Eu realmente não suporto scripts que me façam perguntas em vez de permitir que eu use opções de linha de comando (mais fácil de editar e reutilizar linhas de comando anteriores, mais fácil de usar em um script), então usaria getopts
assim:
#!/bin/bash
regions=(us-east-1 us-west-2 us-west-1 eu-central-1 ap-southeast-1
ap-northeast-1 ap-southeast-2 ap-northeast-2 ap-south-1
sa-east-1)
region=0 # default to region 0, us-east-1
usage() {
[ -n "$1" ] && printf '%s\n\n' "$@"
echo "Usage: $0 [ -r region-number|\"list\"] ..."
# print more help here
exit 1
}
list_regions() {
[ -n "$1" ] && printf '%s\n\n' "$@"
printf '%s\n' "${regions[@]}" | cat -n
exit 1
}
check_region() {
[ "$region" == "list" ] && list_regions
[[ ! "$region" =~ ^[0-9]+$ ]] && usage "Region code must be numeric"
region=$((region - 1)) # bash arrays are zero-based
[ -z "${regions[$region]}" ] || \
[ "$region" -lt 0 ] && list_regions "Unknown region code"
}
while getopts 'r:h' opt ; do
case "$opt" in
r) region="$OPTARG" ; check_region ;;
h) usage ;;
*) usage ;;
esac
done
shift $(($OPTIND - 1))
# do whatever with "$region" and/or "${regions[$region]}"
echo region="${regions[$region]}"
Alguns exemplos são executados:
$ ./busted.sh
region=us-east-1
$ ./busted.sh -r
./busted.sh: option requires an argument -- r
Usage: ./busted.sh [-r region-number|"list"] ...
$ ./busted.sh -r list
1 us-east-1
2 us-west-2
3 us-west-1
4 eu-central-1
5 ap-southeast-1
6 ap-northeast-1
7 ap-southeast-2
8 ap-northeast-2
9 ap-south-1
10 sa-east-1
$ ./busted.sh -r 99
Unknown region code
1 us-east-1
2 us-west-2
3 us-west-1
4 eu-central-1
5 ap-southeast-1
6 ap-northeast-1
7 ap-southeast-2
8 ap-northeast-2
9 ap-south-1
10 sa-east-1
$ ./busted.sh -r 7
region=ap-southeast-2
Você poderia fazer algo assim:
valid=(foo bar doo)
echo enter something, valid values: "${valid[@]}"
read text
ok=0
for x in "${valid[@]}" ; do
if [ "$text" = "$x" ] ; then ok=1 ; fi ;
done
echo is it ok: $ok
Os valores válidos são salvos em uma matriz bash, que pode ser usada para exibição e para testar a string de entrada.
Além do fato de que -o
in test
precisa de uma condição completa, há também argumentos que não se deve usar
[ "$x" != "foo" -a "$x" != "bar" ]
mas em vez disso
[ "$x" != "foo" ] && [ "$x" != "bar" ]
Tags bash shell scripting shell-script