Recuerdo haber visto en alguna parte una bashsecuencia de comandos que usa casey shiftrecorre la lista de parámetros posicionales, analiza indicadores y opciones con argumentos cuando los encuentra, y los elimina después del análisis para dejar solo los argumentos desnudos, que luego son procesados por el resto del guión.
Por ejemplo, al analizar la línea de comando de cp -R file1 -t /mybackup file2 -f, primero caminaría a través de los parámetros, reconocería que el usuario ha solicitado descender a directorios por -R, especificó el objetivo por -t /mybackupy para forzar la copia -fy eliminará de la lista de parámetros, dejando el programa a procesar file1 file2como los argumentos restantes.
Pero parece que no puedo recordar / descubrir el guión que vi cada vez. Solo me gustaría poder hacer eso. He estado buscando en varios sitios y agrego una lista de páginas relevantes que examiné.
Una pregunta en este sitio web preguntó específicamente sobre "opciones independientes del orden", pero tanto la respuesta única como la respuesta a la pregunta a la que fue duplicada no considera casos como el anterior donde las opciones se mezclan con argumentos normales, lo que supongo que fue razón para que la persona mencione específicamente opciones independientes del pedido .
Como bashla función incorporada getoptsparece detenerse en el primer argumento sin opción, no parece ser suficiente como solución. Es por eso que la página de Wooledge BashFAQ (ver más abajo) explica cómo reorganizar los argumentos. Pero me gustaría evitar crear múltiples matrices en caso de que la lista de argumentos sea bastante larga.
Dado shiftque no admite la aparición de argumentos individuales en el medio de la lista de parámetros, no estoy seguro de cuál es una forma directa de implementar lo que estoy preguntando.
Me gustaría saber si alguien tiene alguna solución para eliminar argumentos del medio de la lista de parámetros sin crear una matriz completamente nueva.
Páginas que ya he visto:
- http://mywiki.wooledge.org/ComplexOptionParsing#Rearranging_arguments
- http://mywiki.wooledge.org/BashFAQ/035
- Uso de getopts en el script de shell bash para obtener opciones de línea de comando largas y cortas
- http://wiki.bash-hackers.org/scripting/posparams
- http://wiki.bash-hackers.org/howto/getopts_tutorial
- argumento de bash para argumentos en $ @
- ¿Cuál es la forma canónica de implementar opciones independientes del orden en los scripts de bash?
- ¿Cómo manejo los interruptores en un script de shell?

Respuestas:
POSIXY, el análisis de las opciones debe detenerse en
--el primer argumento sin opción (o sin argumento de opción), lo que ocurra primero. Entonces enEso es al
file1, por lo quecpde forma recursiva deben copiar todosfile1,-t,/mybackupyfile2en el-fdirectorio.getopt(3)Sin embargo, GNU (que GNUcpusa para analizar opciones (y aquí está usando GNUcpya que está usando la-topción específica de GNU )), a menos que se establezca la$POSIXLY_CORRECTvariable de entorno, acepta opciones después de argumentos. Por lo tanto, en realidad es equivalente al análisis de estilo de opción POSIX:El
getoptsshell incorporado, incluso en el shell GNU (bash) solo maneja el estilo POSIX. Tampoco admite opciones largas u opciones con argumentos opcionales.Si desea analizar las opciones de la misma manera que lo
cphace GNU , deberá usar lagetopt(3)API de GNU . Para eso, si está en Linux, puede usar lagetoptutilidad mejorada deutil-linux( esa versión mejorada delgetoptcomando también se ha portado a otros Unices como FreeBSD ).Eso
getoptreorganizará las opciones de una manera canónica que le permite analizarlo simplemente con unwhile/casebucle.Normalmente lo usarías como:
También tenga en cuenta que
getoptanalizará las opciones de la misma manera que locphace GNU . En particular, admite las opciones largas (y al ingresarlas abreviadas) y respeta las$POSIXLY_CORRECTvariables de entorno (que, cuando se configuran, desactivan el soporte para las opciones después de los argumentos) de la misma manera que locphace GNU .Tenga en cuenta que usar gdb e imprimir los argumentos que
getopt_long()recibe puede ayudar a construir los parámetros paragetopt(1):Entonces puedes usarlo
getoptcomo:Recuerde que
cpla lista de opciones compatibles de GNU puede cambiar de una versión a la siguiente y esogetoptno podrá verificar si pasa un valor legal a la--sparseopción, por ejemplo.fuente
while [ "$#" -gt 0 ]io justwhile (($#))? ¿Es solo para evitar un bashismo?(($#))es más un kshismo .Por lo tanto, cada vez que
getoptsprocesa un argumento, no espera que establezca la variable de shell$OPTINDen el siguiente número en la lista de argumentos que debe procesar y devuelve otro que no sea 0. Si$OPTINDse establece en un valor de 1,getoptsse especifica POSIX para aceptar un nueva lista de argumentos Por lo tanto, esto solo observa elgetoptsretorno, guarda los incrementos de un contador más$OPTINDpara cualquier retorno fallido, aleja los argumentos fallidos y restablece$OPTINDcada intento fallido. Puede usarlo comoopts "$@"si quisiera personalizar elcasebucle o guardarlo en una variable y cambiar esa sección aeval $case.Mientras se ejecuta, establece
$argstodos los argumentos quegetoptsno manejan ... así que ...SALIDA
Esto funciona
bash,dash,zsh,ksh93,mksh... bueno, dejar de tratar en ese punto. En cada caparazón también consiguió$[Rtf]flagy$targ. El punto es que todos los números para los argumentos quegetoptsno quisieron procesar permanecieron.Cambiar el estilo de opciones tampoco hizo ninguna diferencia. Funcionó como
-Rf -t/mybackupo-R -f -t /mybackup. Funcionó en el medio de la lista, al final de la lista, o al principio de la lista ...Aún así, la mejor manera es simplemente pegar un
--final de opciones en su lista de argumentos y luego hacerloshift "$(($OPTIND-1))"al final de unagetoptsejecución de procesamiento. De esa manera, elimina todos los parámetros procesados y mantiene el final de la lista de argumentos.Una cosa que me gusta hacer es traducir las opciones largas a cortas, y lo hago de una manera muy similar, por eso esta respuesta fue fácil, antes de correr
getopts.fuente
cp -t --file fooocp -- --file foo) y no haría frente a las opciones ingresadas abreviadas (--fi...), o con la--target=/destsintaxis.getoptscosa con una función mucho más simple.opts()tiene algo que ver con su propia respuesta, ya queopts()funciona en un solo bucle, tocando cada argumento pero una vez, y lo hace de manera confiable (lo más cerca que puedo decir) , de forma portátil y sin una sola subshell.-R,-t /mybackup,-f). Mantendré mi voto negativo por ahora, ya que todavía está ofuscado, lo está usando sin$ainicializar yargs= opts...es probable que deje sinargsconfigurar (o establecer lo que era antes) después deoptsregresar en muchos shells (que incluye bash).bash- Odio eso. En mi opinión, si la función es una función de shell actual que debería conservarse. Estoy abordando estas cosas, ya que la función actual, con más pruebas, se podría hacer de manera robusta para manejar todos los casos e incluso para marcar el argumento con su opción anterior, pero no estoy de acuerdo con que esté ofuscado . Tal como está escrito, es el medio más simple y directo de cumplir su tarea que se me ocurre.testing entoncesshifting tiene poco sentido cuando en cadashiftcaso fallido deberíasreturn. No tiene la intención de hacer lo contrario.