Não sei, getopt
mas o getopts
builtin pode ser usado para lidar apenas com opções longas como esta:
while getopts :-: o
do case "$o$OPTARG" in
(-longopt1) process ;;
(-longopt2) process ;;
esac; done
Obviamente, como está, isso não funciona se as opções longas tiverem argumentos. Isso pode ser feito, porém, mas, como aprendi a trabalhar nisso. Enquanto o incluí inicialmente aqui, percebi que, para opções longas, ele não tem muita utilidade. Nesse caso, estava apenas diminuindo meus case
(match)
campos com um único caractere previsível. Agora, o que eu sei é que é excelente para opções curtas - é mais útil quando ele faz um loop sobre uma sequência de tamanho desconhecido e seleciona bytes únicos de acordo com a sequência de opções. Mas quando a opção é o argumento, não há muito o que você está fazendo com uma for var do case $var in
combinação que ele possa fazer. Acho que é melhor manter as coisas simples.
Suspeito que o mesmo seja verdade, getopt
mas não sei o suficiente para dizer com certeza. Dada a seguinte matriz de argumentos, demonstrarei meu próprio analisador de argumentos - que depende principalmente da relação de avaliação / atribuição pela qual apreciei alias
e $((shell=math))
.
set -- this is ignored by default --lopt1 -s 'some '\''
args' here --ignored and these are ignored \
--alsoignored andthis --lopt2 'and
some "`more' --lopt1 and just a few more
Essa é a string arg com a qual trabalharei. Agora:
aopts() { env - sh -s -- "$@"
} <<OPTCASE 3<<\OPTSCRIPT
acase() case "\$a" in $(fmt='
(%s) f=%s; aset "?$(($f)):";;\n'
for a do case "$a" in (--) break;;
(--*[!_[:alnum:]]*) continue;;
(--*) printf "$fmt" "$a" "${a#--}";;
esac;done;printf "$fmt" '--*' ignored)
(*) aset "" "\$a";;esac
shift "$((SHIFT$$))"; f=ignored; exec <&3
OPTCASE
aset() { alias "$f=$(($f${1:-=$(($f))+}1))"
[ -n "${2+?}" ] && alias "${f}_$(($f))=$2"; }
for a do acase; done; alias
#END
OPTSCRIPT
Isso processa a matriz arg de uma de duas maneiras diferentes, dependendo se você entrega um ou dois conjuntos de argumentos separados pelo --
delimitador. Nos dois casos, aplica-se a sequências de processamento na matriz arg.
Se você chamar assim:
: $((SHIFT$$=3)); aopts --lopt1 --lopt2 -- "$@"
Sua primeira ordem de negócios será escrever sua acase()
função para se parecer com:
acase() case "$a" in
(--lopt1) f=lopt1; aset "?$(($f)):";;
(--lopt2) f=lopt2; aset "?$(($f)):";;
(--*) f=ignored; aset "?$(($f)):";;
(*) aset "" "$a";;esac
E ao lado de shift 3
. A substituição de comando na acase()
definição da função é avaliada quando o shell de chamada constrói aqui os documentos de entrada da função, mas acase()
nunca é chamado ou definido no shell de chamada. É chamado no subshell, é claro, e dessa forma você pode especificar dinamicamente as opções de interesse na linha de comando.
Se você entregar uma matriz não delimitada, ela simplesmente será preenchida acase()
com correspondências para todos os argumentos que começam com a sequência --
.
A função realiza praticamente todo o seu processamento no subshell - salvando iterativamente cada um dos valores do arg em aliases atribuídos com nomes associativos. Quando alias
termina , imprime todos os valores salvos com - especificados no POSIX para imprimir todos os valores salvos entre aspas, de forma que seus valores possam ser reinicializados no shell. Então, quando eu faço ...
aopts --lopt1 --lopt2 -- "$@"
Sua saída é assim:
...ignored...
lopt1='8'
lopt1_1='-s'
lopt1_2='some '\'' args'
lopt1_3='here'
lopt1_4='and'
lopt1_5='just'
lopt1_6='a'
lopt1_7='few'
lopt1_8='more'
lopt2='1'
lopt2_1='and
some "`more'
Enquanto percorre a lista arg, verifica se há uma correspondência no bloco de casos. Se encontrar uma partida, lança uma bandeira - f=optname
. Até encontrar novamente uma opção válida, ele adicionará cada argumento subsequente a uma matriz criada com base no sinalizador atual. Se a mesma opção for especificada várias vezes, os resultados serão compostos e não substituirão. Qualquer coisa que não esteja no caso - ou qualquer argumento após as opções ignoradas - é atribuída a uma matriz ignorada .
A saída é protegida pelo shell para entrada do shell automaticamente pelo shell, e assim:
eval "$(: $((SHIFT$$=3));aopts --lopt1 --lopt2 -- "$@")"
... deve ser perfeitamente seguro. Se, por algum motivo, não for seguro, provavelmente você deve registrar um relatório de erro com o mantenedor do shell.
Ele atribui dois tipos de valores de alias para cada correspondência. Primeiro, ele define um sinalizador - isso ocorre se uma opção precede ou não argumentos não correspondentes. Portanto, qualquer ocorrência --flag
na lista arg será acionada flag=1
. Isso não é composto - --flag --flag --flag
apenas recebe flag=1
. Esse valor é incrementado - para quaisquer argumentos que possam segui-lo. Pode ser usado como uma chave de índice. Depois de fazer o eval
acima, eu posso fazer:
printf %s\\n "$lopt1" "$lopt2"
...para obter...
8
1
E entao:
for o in lopt1 lopt2
do list= i=0; echo "$o = $(($o))"
while [ "$((i=$i+1))" -le "$(($o))" ]
do list="$list $o $i \"\${${o}_$i}\" "
done; eval "printf '%s[%02d] = %s\n' $list"; done
RESULTADO
lopt1 = 8
lopt1[01] = -s
lopt1[02] = some ' args
lopt1[03] = here
lopt1[04] = and
lopt1[05] = just
lopt1[06] = a
lopt1[07] = few
lopt1[08] = more
lopt2 = 1
lopt2[01] = and
some "`more
E para args que não correspondiam eu substituiria ignorado no for ... in
campo acima para obter:
ignored = 10
ignored[01] = this
ignored[02] = is
ignored[03] = ignored
ignored[04] = by
ignored[05] = default
ignored[06] = and
ignored[07] = these
ignored[08] = are
ignored[09] = ignored
ignored[10] = andthis
getopts
, mas está usando o/usr/bin/getopt
comando