Estou tentando criar um script de shell que aceita várias opções e getopts
parece ser uma boa solução, pois pode lidar com a ordem variável das opções e argumentos (eu acho!).
Usarei apenas opções curtas e cada opção curta exigirá um valor correspondente, por exemplo: ./command.sh -a arga -g argg -b argb
mas gostaria de permitir que as opções fossem inseridas em uma ordem não específica, como é o modo como a maioria das pessoas está acostumada a trabalhar com comandos do shell .
O outro ponto é que eu gostaria de fazer minha própria verificação dos valores dos argumentos das opções, idealmente dentro das case
instruções. A razão para isso é que meus testes :)
em minha case
declaração produziram resultados inconsistentes (provavelmente por falta de entendimento da minha parte).
Por exemplo:
#!/bin/bash
OPTIND=1 # Reset if getopts used previously
if (($# == 0)); then
echo "Usage"
exit 2
fi
while getopts ":h:u:p:d:" opt; do
case "$opt" in
h)
MYSQL_HOST=$OPTARG
;;
u)
MYSQL_USER=$OPTARG
;;
p)
MYSQL_PASS=$OPTARG
;;
d)
BACKUP_DIR=$OPTARG
;;
\?)
echo "Invalid option: -$OPTARG" >&2
exit 2;;
:)
echo "Option -$OPTARG requires an argument" >&2
exit 2;;
esac
done
shift $((OPTIND-1))
echo "MYSQL_HOST='$MYSQL_HOST' MYSQL_USER='$MYSQL_USER' MYSQL_PASS='$MYSQL_PASS' BACKUP_DIR='$BACKUP_DIR' Additionals: $@"
Estava falhando em ocorrências como esta ... ./command.sh -d -h
Quando eu quero sinalizar -d como exigindo um argumento, mas recebo o valor de -d=-h
que não é o que eu preciso.
Portanto, imaginei que seria mais fácil executar minha própria validação nas instruções de caso para garantir que cada opção seja definida e definida apenas uma vez.
Estou tentando fazer o seguinte, mas meus if [ ! "$MYSQL_HOST" ]; then
bloqueios não são acionados.
OPTIND=1 # Reset if getopts used previously
if (($# == 0)); then
echo "Usage"
exit 2
fi
while getopts ":h:u:p:d:" opt; do
case "$opt" in
h)
MYSQL_HOST=$OPTARG
if [ ! "$MYSQL_HOST" ]; then
echo "host not set"
exit 2
fi
;;
u)
MYSQL_USER=$OPTARG
if [ ! "$MYSQL_USER" ]; then
echo "username not set"
exit 2
fi
;;
p)
MYSQL_PASS=$OPTARG
if [ ! "$MYSQL_PASS" ]; then
echo "password not set"
exit 2
fi
;;
d)
BACKUP_DIR=$OPTARG
if [ ! "$BACKUP_DIR" ]; then
echo "backup dir not set"
exit 2
fi
;;
\?)
echo "Invalid option: -$OPTARG" >&2
exit 2;;
#:)
# echo "Option -$opt requires an argument" >&2
# exit 2;;
esac
done
shift $((OPTIND-1))
echo "MYSQL_HOST='$MYSQL_HOST' MYSQL_USER='$MYSQL_USER' MYSQL_PASS='$MYSQL_PASS' BACKUP_DIR='$BACKUP_DIR' Additionals: $@"
Existe uma razão pela qual não consigo verificar se uma OPTARG
tem comprimento zero a partir de dentro getopts ... while ... case
?
Qual é a melhor maneira de executar minha própria validação de argumento getopts
em um caso em que não quero depender da :)
. Executar minha validação de argumento fora do while ... case ... esac
?
Então eu poderia acabar com valores de argumento de -d
etc e não pegar uma opção que faltava.
while
loop sobre as opções. Esse é o método que eu uso, embora seja detalhado em comparação com outros, é muito claro o que está acontecendo no script. E a manutenção por outros é importante neste caso.