Eu escrevi o script a seguir bash
como uma ferramenta de orçamento para calcular com mais precisão (e moderar) quando comprei um maço de cigarros pela última vez.
Além -h
de imprimir a saída, é preciso uma outra opção: -b
com (o que se pretende) um parâmetro opcional para definir o deslocamento em horas. Então -b 5
registra um novo pacote de cigarros comprado há 5 horas, e as execuções subsequentes cigs.sh
indicam quantas semanas, dias ou horas se passaram desde então. Se o tempo decorrido desde a última vez que comprei um pacote for menor que $threshold
, a saída será impressa em vermelho; se o tempo decorrido for maior que $threshold
, a saída será verde, indicando que agora está "ok" para eu comprar um novo pacote.
Eu consegui fazer tudo isso funcionar bem, exceto por uma coisa: atualmente não é possível especificar -b
sem um deslocamento (ou seja, registrar a compra como sendo feita agora em vez de algumas horas no passado). Até onde eu pude dizer, isso parece ser uma limitação de getopts
: sem os dois pontos em b:h
, $OPTARG falha ao preencher fazendo com que a lógica na b)
opção case falhe; com os dois pontos, impede que -b
seja usado sem parâmetro, lançando o seguinte erro:
/usr/local/bin/scripts/cigs.sh: opção requer um argumento -- b
Parâmetro desconhecido passado: -b
Aqui está a getopts
parte do meu script:
while getopts "b:h" OPTION; do
case $OPTION in
h)
echo "$usage"
exit
;;
b)
offset=$OPTARG
if [[ -n $offset && ! $offset =~ ^[0-9]+$ ]]; then
echo "HOURS parameter passed to -b must be an integer."
exit
fi
echo -e "Bought a new $item...\nResetting timer to 0 days and $offset hours."
offset=$((offset*60*60))
last_bought="$(date -u +%s)"
new_lb=$((last_bought-offset))
echo $new_lb > $lb_file
exit
;;
*)
echo "Unknown parameter passed: $1"
exit 1
;;
esac
done
Questão muito interessante aqui. Com base no que entendo sobre como
getopts
funciona, esse uso de dois pontos (:
) significa que o valor da opção deve ser definido:E se você quisesse que fosse opcional, precisaria definir dois dois pontos (
::
) e também não ter nada seguindo assim:Mas isso
hb::
não funciona.Eu brinquei com seu script e esta é a única solução que consegui trabalhar. Ele altera o seu
getopts "b:h"
paragetopts "bh"
que ambos os parâmetros de opção sejam opcionais. Mas a mágica está em adicionar mais código aob)
caso, então todo owhile
pedaço agora se parece com isso:A mágica vem deste pedaço aqui que é baseado nesta outra resposta do Stack Overflow para uma pergunta sobre o mesmo problema:
Claramente não tão limpo quanto o que seria de esperar se
getopts "hb::"
funcionasse, mas não funciona, então esse kludge funciona.Se alguém mais experiente com o Bash puder explicar por que - ou apresentar uma solução mais limpa - eles devem publicá-lo. Por enquanto, isso funciona, então funciona!