É porque toda a sua lógica depende do $OPT_[AB]
sendo nulo. Mas, mesmo que você não passe um parâmetro -[ab] $OPTARG
, ainda estará definindo-os na parte superior do script com OPT_[AB]=[AB]
. Então suas cadeias lógicas nunca passam da raiz ...
if [[ -z $OPT_A ]]; then...
... declaração.
Bem ... não tudo da sua lógica depende disso. Você também está fazendo:
shift $((OPTIND-1))
while [ $# -ne 0 ]...
Então, se você passou script -a arg
, então getopts
definiria $OPT_A
para arg
e $OPTIND
chegaria a 3. Então você shift 2
(todos os seus posicionais) então falhar imediatamente o teste em while
. Portanto, seu case
definiria $OPT_A
e a próxima coisa que acontece é exit 0
. Então, eu acho que você nunca teria que procurar um $OPT_A
vazio de qualquer forma.
E mesmo isso seria ok, já que a maior parte de sua lógica é projetada para testar falhas - mas seu script somente exit
s. Você provavelmente faz o $OPT_A
var, mas não faz nada com ele. Você não pode usar esse valor depois do script exit
s - não sem algum IPC predefinido, mas não há nada disso aqui. O script é chamado em um subshell e os valores que ele configura são perdidos quando ele retorna ao shell pai.
O que é mais, o optstring :a:b
não permite um $OPTARG
a -b
. Um cólon principal na optstring significa operação silenciosa - ele não grava em stderr
se houver um problema com as opções ou seus argumentos. Mas um cólon arrastando uma opção é o que significa que a opção deve esperar um argumento. Como:
while getopts :a:b: FLAG
... isso indicaria duas opções que esperam argumentos. Pode ser complicado, porque se você indicar que ele deveria receber um argumento, então se getopts
o encontrar sem um, ele o sinaliza como um erro:
sh -c 'getopts :a:b: opt -a; echo "$opt $OPTARG"'
... que imprime ...
: a
Nesse caso, a opção acaba em $OPTARG
e a :
acaba em $opt
. É mais claro se estamos menos :
quietos sobre isso:
sh -c 'getopts a:b: opt -a; echo "$opt $OPTARG"'
No arg for -a option
Então, você precisa verificar :
colon e ?
- que é outro tipo de erro e que é reencaminhado convencionalmente para imprimir algum tipo de coisa curta em --help
.
Pessoalmente, eu me certificaria de que $OPT_[AB]
estavam vazios para começar, faça alguma lógica para configurá-los corretamente e, quando terminar o loop de teste, faça o último teste para um valor nulo. Se eles não têm qualquer valor, então deve ser por algum motivo que não tenho tratado, e é um erro, independentemente. Aqui está um começo de como eu iria trabalhar nesse loop de teste ...
param_err(){
set '' "$@"
: "${1:?Parameter '$OPTARG' does not look like an IP Address $2}"
}
test_oct(){
oIFS=$IFS; unset "${IFS+o}oIFS"; IFS=.
for oct in $1; do [ $oct -lt 256 ] ||
param_err "('$oct' too large)"
done; unset IFS oct
: "${oIFS+${IFS=$oIFS}}"
}
a_param()
case ${1##*.*.*.*.*} in (a) OPT_A=A;; #some default - no arg provided
(.*|*..*|*.) param_err '(empty octet)';;
(*[!.0-9]*) param_err '(octet is not positive integer)';;
(*.*.*.*) test_oct "$1"; OPT_A=$1;;
(*?*) param_err '(too few octets)';;
(*) param_err ${1:+"(too many octets)"} '(null param)';;
esac
unset OPT_A OPT_B
while getopts :a:b:c:d: opt
do case ${opt#:}$OPTARG in
a*) a_param "$OPTARG";;
b*) b_param "$OPTARG";; #tests as needed similar to a_param()
?*) help;; #param_err should call this too, but it just exits
esac
done