A solução para esse problema requer algo diferente de getopt porque getopt reorganiza as opções que ele encontra que correspondem à especificação da opção e termina em opções não reconhecidas. O getopts embutido do Bash vem para o resgate, mas precisa ser capaz de lidar com opções longas. Em uma postagem de Arvid Requate e TomRoche , há um "truque" que permite que o getopts lide com opções longas: use - como uma especificação de opção e use dois pontos principais no especificação de opções para silenciar o relatório de erros. Sua solução, no entanto, exigiria que o código fosse duplicado para lidar com opções curtas e longas.
Aqui está uma solução que testei e atende a todos os meus requisitos, além de não duplicar o processamento de opções curtas e longas. Para maior clareza e integridade, mudei username para set e adicionei toggle para demonstrar opções que não aceitam valores.
parse.sh
#!/bin/bash
Options=("$@")
while getopts ":s:-:" OptChar "${Options[@]}"; do
case "$OptChar" in
-) case "$OPTARG" in
set|set=*)
if [[ $OPTARG =~ ^set= ]] ; then
Value="${Options[$OPTIND-2]#*=}"
else
Value="${Options[$OPTIND-1]}"
((OPTIND++))
fi
echo "Parsed: --$OPTARG, value: '$Value'"
;;
toggle)
echo "Parsed: --$OPTARG";;
*) ((OPTIND--)); break;;
esac
;;
# Redirect short arguments to long arguments
s) ((OPTIND-=2)); Options[OPTIND-1]="--set";;
t) ((OPTIND--)); Options[OPTIND-1]="--toggle";;
*) ((OPTIND--)); break;;
esac
done
Options=( "${Options[@]:$OPTIND-1}" )
echo "REMAINING Options: ${Options[@]}"
e aqui está o meu código de teste:
% ./parse.sh --set=a -s b --set= --set c --unknown -s d --set e
Parsed: --set=a, value: 'a'
Parsed: --set, value: 'b'
Parsed: --set=, value: ''
Parsed: --set, value: 'c'
REMAINING Options: --unknown -s d --set e
%
% ./parse.sh -s a -x -s b
Parsed: --set, value: 'a'
REMAINING Options: -x -s b
%