No sé, getopt
pero el getopts
incorporado puede usarse para manejar solo opciones largas como esta:
while getopts :-: o
do case "$o$OPTARG" in
(-longopt1) process ;;
(-longopt2) process ;;
esac; done
Por supuesto, como está, eso no funciona si se supone que las opciones largas tienen argumentos. Sin embargo, se puede hacer, pero, como he aprendido trabajando en esto. Aunque inicialmente lo incluí aquí, me di cuenta de que para las opciones largas no tiene mucha utilidad. En este caso, solo estaba acortando mis case
(match)
campos en un solo carácter predecible. Ahora, lo que sé, es que es excelente para las opciones cortas: es más útil cuando se repite en una cadena de longitud desconocida y selecciona bytes individuales de acuerdo con su cadena de opciones. Pero cuando la opción es el argumento, no hay mucho que estés haciendo con una for var do case $var in
combinación que podría hacer. Creo que es mejor mantenerlo simple.
Sospecho que lo mismo es cierto, getopt
pero no sé lo suficiente para decirlo con certeza. Dada la siguiente matriz arg, demostraré mi propio analizador arg pequeño, que depende principalmente de la relación de evaluación / asignación por la que he llegado a apreciar alias
y $((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
Esa es la cadena arg con la que trabajaré. Ahora:
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
Eso procesa la matriz arg de una de dos formas diferentes dependiendo de si le entrega uno o dos conjuntos de argumentos separados por el --
delimitador. En ambos casos se aplica a secuencias de procesamiento a la matriz arg.
Si lo llamas así:
: $((SHIFT$$=3)); aopts --lopt1 --lopt2 -- "$@"
Su primer orden del día será escribir su acase()
función para que se vea así:
acase() case "$a" in
(--lopt1) f=lopt1; aset "?$(($f)):";;
(--lopt2) f=lopt2; aset "?$(($f)):";;
(--*) f=ignored; aset "?$(($f)):";;
(*) aset "" "$a";;esac
Y al lado de shift 3
. La sustitución de comandos en la acase()
definición de la función se evalúa cuando el shell de llamada construye los documentos de entrada de la función aquí, pero acase()
nunca se llama o define en el shell de llamada. Sin embargo, se llama en la subshell, por lo que de esta manera puede especificar dinámicamente las opciones de interés en la línea de comando.
Si le entrega una matriz no delimitada, simplemente se completa acase()
con coincidencias para todos los argumentos que comienzan con la cadena --
.
La función realiza prácticamente todo su procesamiento en la subshell, guardando iterativamente cada uno de los valores de los argumentos en los alias asignados con nombres asociativos. Cuando alias
termina , imprime todos los valores con los que guardó , que está especificado por POSIX para imprimir todos los valores guardados citados de tal manera que sus valores puedan reintroducirse en el shell. Entonces cuando lo hago ...
aopts --lopt1 --lopt2 -- "$@"
Su salida se ve así:
...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'
A medida que recorre la lista de argumentos, comprueba si el bloque de casos coincide. Si encuentra una coincidencia allí, arroja una bandera - f=optname
. Hasta que una vez más encuentre una opción válida, agregará cada argumento posterior a una matriz que construya en función del indicador actual. Si la misma opción se especifica varias veces, los resultados se combinan y no se anulan. Cualquier cosa que no esté en el caso, o cualquier argumento que siga a las opciones ignoradas, se asignan a una matriz ignorada .
La salida es segura para la entrada de shell automáticamente por el shell, y así:
eval "$(: $((SHIFT$$=3));aopts --lopt1 --lopt2 -- "$@")"
... debería ser perfectamente seguro. Si por alguna razón no es seguro, entonces probablemente debería presentar un informe de error con su encargado de mantenimiento de shell.
Asigna dos tipos de valores de alias para cada coincidencia. Primero, establece un indicador: esto ocurre independientemente de si una opción precede a argumentos no coincidentes. Por lo tanto, cualquier aparición --flag
en la lista arg se disparará flag=1
. Esto no se complica, --flag --flag --flag
solo se pone flag=1
. Sin embargo, este valor se incrementa para cualquier argumento que pueda seguirlo. Se puede usar como clave de índice. Después de hacer lo eval
anterior, puedo hacer:
printf %s\\n "$lopt1" "$lopt2"
...Llegar...
8
1
Y entonces:
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
SALIDA
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
Y para los argumentos que no coincidían, sustituiría ignorado en el for ... in
campo anterior para obtener:
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
, pero está utilizando el/usr/bin/getopt
comando.