Digamos, tengo un script que se llama con esta línea:
./myscript -vfd ./foo/bar/someFile -o /fizz/someOtherFile
o este:
./myscript -v -f -d -o /fizz/someOtherFile ./foo/bar/someFile
¿Cuál es la forma aceptada de este análisis de manera que en cada caso (o alguna combinación de los dos) $v, $fy $dtodos se ponen a truey $outFileserán iguales a /fizz/someOtherFile?

zparseopts -D -E -M -- d=debug -debug=dY tener ambos-dy--debugen la$debugmatrizecho $+debug[1]devolverá 0 o 1 si se usa uno de esos. Ref: zsh.org/mla/users/2011/msg00350.htmlRespuestas:
Método # 1: Usando bash sin getopt [s]
Dos formas comunes de pasar argumentos par clave-valor son:
Bash Separado por espacio (p. Ej.
--option argument) (Sin getopt [s])Uso
demo-space-separated.sh -e conf -s /etc -l /usr/lib /etc/hostssalida de copiar y pegar el bloque de arriba:
Bash Equals-Separated (eg,
--option=argument) (sin getopt [s])Uso
demo-equals-separated.sh -e=conf -s=/etc -l=/usr/lib /etc/hostssalida de copiar y pegar el bloque de arriba:
Para comprender mejor,
${i#*=}busque "Eliminación de subcadenas" en esta guía . Es funcionalmente equivalente a lo`sed 's/[^=]*=//' <<< "$i"`que llama un subproceso innecesario o lo`echo "$i" | sed 's/[^=]*=//'`que llama a dos subprocesos innecesarios.Método # 2: Usando bash con getopt [s]
de: http://mywiki.wooledge.org/BashFAQ/035#getopts
limitaciones de getopt (1) (
getoptversiones anteriores, relativamente recientes ):Las
getoptversiones más recientes no tienen estas limitaciones.Además, la oferta de shell POSIX (y otros)
getoptsque no tiene estas limitaciones. He incluido ungetoptsejemplo simplista .Uso
demo-getopts.sh -vf /etc/hosts foo barsalida de copiar y pegar el bloque de arriba:
Las ventajas de
getoptsson:dash.-vf filenameen la forma típica de Unix, automáticamente.La desventaja
getoptses que solo puede manejar opciones cortas (-hno--help) sin código adicional.Hay un tutorial de getopts que explica lo que significan todas las sintaxis y variables. En bash, también hay
help getopts, que podría ser informativo.fuente
getoptque incluye toda la funcionalidad degetoptsy más.man getopten las salidas de Ubuntu 13.04getopt - parse command options (enhanced)como nombre, por lo que supongo que esta versión mejorada es estándar ahora.getoptno es una utilidad GNU, es parte deutil-linux.-gt 0, elimine sushiftdespués deesac, aumente todoshiftpor 1 y agregue este caso:*) break;;puede manejar argumentos no opcionales. Ej: pastebin.com/6DJ57HTc–default. En el primer ejemplo, noto que si–defaultes el último argumento, no se procesa (se considera como no opt), a menos quewhile [[ $# -gt 1 ]]se establezca comowhile [[ $# -gt 0 ]]Ninguna respuesta menciona getopt mejorado . Y la respuesta más votada es engañosa: ignora
-vfdlas opciones cortas de estilo (solicitadas por el OP) u opciones después de argumentos posicionales (también solicitados por el OP); e ignora los errores de análisis. En lugar:getoptde util-linux o anteriormente GNU glibc . 1getopt_long()la función C de GNU glibc.getoptno puede hacer esto)script.sh -o outFile file1 file2 -v(getoptsno hace esto)=opciones largas de estilo:script.sh --outfile=fileOut --infile fileIn(permitir que ambas sean largas si se analiza automáticamente)-vfd(trabajo real si se analiza automáticamente)-oOutfileo-vfdoOutfilegetopt --test→ valor de retorno 4.getopto de concha incorporadagetoptsson de uso limitado.Las siguientes llamadas
todo vuelve
con lo siguiente
myscript1 getopt mejorado está disponible en la mayoría de los "sistemas bash", incluido Cygwin; en OS X intente brew install gnu-getopt o
sudo port install getopt2 las
exec()convencionesPOSIXno tienen una forma confiable de pasar NULL binario en los argumentos de la línea de comandos; esos bytes finalizan prematuramente laprimera versióndel argumento3 lanzada en 1997 o antes (solo lo rastreé hasta 1997)
fuente
getoptes el camino a seguir.getoptes que no se puede usar convenientemente en scripts de envoltura donde uno podría tener pocas opciones específicas para la secuencia de comandos de envoltura, y luego pasar las opciones de la secuencia de comandos no envolvente al ejecutable envuelto, intacto. Digamos que tengo ungrepcontenedor llamadomygrepy tengo una opción--fooespecífica paramygrep, entonces no puedo hacerlomygrep --foo -A 2, y tengo el-A 2pase automáticamentegrep; Yo necesito hacermygrep --foo -- -A 2. Aquí está mi implementación además de su solución.man bashManera más sucinta
script.sh
Uso:
fuente
while [[ "$#" > 1 ]]si quiero soportar terminar la línea con una bandera booleana./script.sh --debug dev --uglify fast --verbose. Ejemplo: gist.github.com/hfossli/4368aa5a577742c3c9f9266ed214aa58./script.sh -d dev -d prod, resultaría endeploy == 'prod'. Lo usé de todos modos: P :): +1:./script.sh -d, no generaría un error, sino que solo se establecería$deployen una cadena vacía.de: digitalpeer.com con modificaciones menores
Uso
myscript.sh -p=my_prefix -s=dirname -l=libnamePara comprender mejor,
${i#*=}busque "Eliminación de subcadenas" en esta guía . Es funcionalmente equivalente a lo`sed 's/[^=]*=//' <<< "$i"`que llama un subproceso innecesario o lo`echo "$i" | sed 's/[^=]*=//'`que llama a dos subprocesos innecesarios.fuente
mount -t tempfs .... Probablemente se pueda arreglar esto a través de algo comowhile [ $# -ge 1 ]; do param=$1; shift; case $param in; -p) prefix=$1; shift;;etc.-vfdlas opciones cortas combinadas de estilo.getopt()/getopts()es una buena opción. Robado de aquí :fuente
$*es uso roto degetopt. (Contiene argumentos con espacios). Vea mi respuesta para un uso adecuado.A riesgo de agregar otro ejemplo para ignorar, aquí está mi esquema.
-n argy--name=argEspero que sea útil para alguien.
fuente
*) die "unrecognized argument: $1"o recopilar los argumentos en una variable*) args+="$1"; shift 1;;.shift 2, emitiendoshiftdos veces en lugar deshift 2. Sugirió la edición.Llegué 4 años tarde a esta pregunta, pero quiero retribuir. Utilicé las respuestas anteriores como punto de partida para ordenar mi antiguo análisis de parámetros ad hoc. Luego reescribí el siguiente código de plantilla. Maneja parámetros largos y cortos, utilizando argumentos separados por espacios o =, así como múltiples parámetros cortos agrupados. Finalmente, vuelve a insertar cualquier argumento que no sea param en las variables $ 1, $ 2 .. Espero que sea útil.
fuente
-c1. Y el uso de=separar opciones cortas de sus argumentos es inusual ...El asunto de escribir un análisis portátil en scripts es tan frustrante que he escrito Argbash , un generador de código FOSS que puede generar el código de análisis de argumentos para su script y tiene algunas características interesantes :
https://argbash.io
fuente
Mi respuesta se basa en gran medida en la respuesta de Bruno Bronosky , pero mezclé sus dos implementaciones de bash puro en una que uso con bastante frecuencia.
Esto le permite tener opciones / valores separados por espacios, así como valores definidos iguales.
Para que pueda ejecutar su script usando:
tanto como:
y ambos deberían tener el mismo resultado final.
PROS:
Permite tanto -arg = value como -arg value
Funciona con cualquier nombre arg que pueda usar en bash
Pura fiesta. No es necesario aprender / usar getopt o getopts
CONTRAS:
No se pueden combinar args.
Estos son los únicos pros / contras en los que puedo pensar fuera de mi cabeza
fuente
Creo que este es lo suficientemente simple como para usar:
Ejemplo de invocación:
fuente
-a=1como estilo argc. Prefiero poner primero la opción principal -opciones y luego las especiales con espaciado simple-o option. Estoy buscando la forma más sencilla de leer argumentos../myscript -v -d fail -o /fizz/someOtherFile -f ./foo/bar/someFilecon su propio script. -d opción no está establecida como d:Ampliando la excelente respuesta de @guneysus, aquí hay un ajuste que permite al usuario usar la sintaxis que prefiera, por ejemplo
vs
Es decir, los iguales se pueden reemplazar con espacios en blanco.
Es posible que esta "interpretación difusa" no sea de su agrado, pero si está creando scripts que son intercambiables con otras utilidades (como es el caso con el mío, que debe funcionar con ffmpeg), la flexibilidad es útil.
fuente
Este ejemplo muestra cómo se utilizan
getoptyeval, yHEREDOC, yshiftpara manejar los parámetros de corto y largo plazo con y sin un valor requerido que sigue. Además, la declaración de cambio / caso es concisa y fácil de seguir.Las líneas más significativas del script anterior son estas:
Corto, directo, legible y maneja casi todo (en mi humilde opinión).
Espero que ayude a alguien.
fuente
Te doy la función
parse_paramsque analizará los parámetros desde la línea de comandos.--alles-alligual a igualall=all)El siguiente script es una demostración de trabajo de copiar y pegar. Vea la
show_usefunción para entender cómo usarparse_params.Limitaciones:
-d 1)--any-paramy-anyparamson equivalenteseval $(parse_params "$@")debe usarse dentro de la función bash (no funcionará en el ámbito global)fuente
show_use "$@"EasyOptions no requiere ningún análisis:
fuente
getopts funciona muy bien si # 1 lo tiene instalado y # 2 tiene la intención de ejecutarlo en la misma plataforma. OSX y Linux (por ejemplo) se comportan de manera diferente a este respecto.
Aquí hay una solución (no getopts) que admite indicadores iguales, no iguales y booleanos. Por ejemplo, podría ejecutar su script de esta manera:
fuente
Así es como lo hago en una función para evitar romper getopts run al mismo tiempo en algún lugar más alto en la pila:
fuente
Ampliando la respuesta de @ bruno-bronosky, agregué un "preprocesador" para manejar algunos formatos comunes:
--longopt=valen--longopt val-xyzen-x -y -z--para indicar el final de las banderasfuente
Hay varias formas de analizar los argumentos de cmdline (por ejemplo, GNU getopt (no portátil) vs BSD (OSX) getopt vs getopts), todos problemáticos. Esta solución es
=separador-vxfEjemplos: cualquiera de
fuente
Me gustaría ofrecer mi versión de análisis de opciones, que permite lo siguiente:
También permite esto (podría ser no deseado):
Debe decidir antes de usar si = se va a usar en una opción o no. Esto es para mantener el código limpio (ish).
fuente
Solución que conserva argumentos no manejados. Demos incluidas.
Aquí está mi solución. Es MUY flexible y, a diferencia de otros, no debería requerir paquetes externos y maneja los argumentos sobrantes limpiamente.
El uso es:
./myscript -flag flagvariable -otherflag flagvar2Todo lo que tiene que hacer es editar la línea de banderas válidas. Antepone un guión y busca todos los argumentos. Luego define el siguiente argumento como el nombre de la bandera, por ejemplo
El código principal (versión corta, detallada con ejemplos más abajo, también una versión con error):
La versión detallada con demos de eco incorporadas:
La última, esta falla si se pasa un argumento inválido.
Pros: lo que hace, se maneja muy bien. Conserva argumentos no utilizados que muchas de las otras soluciones aquí no tienen. También permite que se invoquen variables sin definirse manualmente en el script. También permite la prepoblación de variables si no se proporciona un argumento correspondiente. (Ver ejemplo detallado).
Contras: No se puede analizar una única cadena arg compleja, por ejemplo, -xcvf se procesaría como un solo argumento. Sin embargo, podría escribir un código adicional en el mío que agregue esta funcionalidad.
fuente
Quiero enviar mi proyecto: https://github.com/flyingangel/argparser
Simple como eso. El entorno se rellenará con variables con el mismo nombre que los argumentos.
fuente
Tenga en cuenta que
getopt(1)fue un breve error de vida de AT&T.getopt fue creado en 1984 pero ya enterrado en 1986 porque no era realmente utilizable.
Una prueba del hecho de que
getoptestá muy desactualizado es que lagetopt(1)página de manual todavía menciona en"$*"lugar de"$@"eso, que se agregó a Bourne Shell en 1986 junto con elgetopts(1)shell incorporado para tratar los argumentos con espacios en el interior.Por cierto: si está interesado en analizar opciones largas en scripts de shell, puede ser interesante saber que la
getopt(3)implementación de libc (Solaris) yksh93ambos agregaron una implementación uniforme de opciones largas que admite opciones largas como alias para opciones cortas. Esto causaksh93y laBourne Shellde implementar una interfaz uniforme durante largos opciones a travésgetopts.Un ejemplo de opciones largas tomadas de la página de manual de Bourne Shell:
getopts "f:(file)(input-file)o:(output-file)" OPTX "$@"muestra cuánto tiempo se pueden usar los alias de opción en Bourne Shell y ksh93.
Vea la página del manual de un Bourne Shell reciente:
http://schillix.sourceforge.net/man/man1/bosh.1.html
y la página del manual para getopt (3) de OpenSolaris:
http://schillix.sourceforge.net/man/man3c/getopt.3c.html
y por último, la página del comando man getopt (1) para verificar los $ * obsoletos:
http://schillix.sourceforge.net/man/man1/getopt.1.html
fuente
Escribí un bash helper para escribir una buena herramienta bash
inicio del proyecto: https://gitlab.mbedsys.org/mbedsys/bashopts
ejemplo:
le dará ayuda:
disfruta :)
fuente
Aquí está mi enfoque: usar regexp.
-qwerty-q -w -e--qwerty=para proporcionar atributos, pero las coincidencias de atributos hasta encontrar guión + espacio "delimitador", por lo que en--q=qwe tyqwe tyhay un atributo-o a -op attr ibute --option=att ribu te --op-tion attribute --option att-ributees válidoguión:
fuente
Supongamos que creamos un script de shell llamado de la
test_args.shsiguiente maneraDespués de ejecutar el siguiente comando:
El resultado sería:
fuente
Use "argumentos" del módulo de los módulos bash
Ejemplo:
fuente
Mezcla de argumentos posicionales y basados en banderas
--param = arg (igual delimitado)
Mezclar libremente banderas entre argumentos posicionales:
Se puede lograr con un enfoque bastante conciso:
--param arg (espacio delimitado)
Por lo general, es más claro no mezclar
--flag=valuey--flag valuepeinar.Es un poco difícil de leer, pero aún es válido.
Fuente
fuente
Aquí hay un getopts que logra el análisis con un código mínimo y le permite definir lo que desea extraer en un caso usando eval con subcadena.
Básicamente
eval "local key='val'"Declara las variables como locales en lugar de globales como la mayoría de las respuestas aquí.
Llamado:
El $ {k: 3} es básicamente una subcadena para eliminar el primero
---de la clave.fuente
Esto también puede ser útil para saber, puede establecer un valor y si alguien proporciona información, anule el valor predeterminado con ese valor.
myscript.sh -f ./serverlist.txt o simplemente ./myscript.sh (y toma los valores predeterminados)
fuente
Otra solución sin getopt [s], POSIX, antiguo estilo Unix
Similar a la solución que Bruno Bronosky publicó aquí es una sin el uso de
getopt(s).La principal característica diferenciadora de mi solución es que permite tener opciones concatenadas juntas como
tar -xzf foo.tar.gzes igual atar -x -z -f foo.tar.gz. Y al igual que entar,psetc. el guión principal es opcional para un bloque de opciones cortas (pero esto se puede cambiar fácilmente). Las opciones largas también son compatibles (pero cuando un bloque comienza con uno, se requieren dos guiones iniciales).Código con opciones de ejemplo
Para el uso de ejemplo, vea los ejemplos más abajo.
Posición de opciones con argumentos
Por lo que vale, las opciones con argumentos no son las últimas (solo las opciones largas deben ser). Entonces, por ejemplo, en
tar(al menos en algunas implementaciones) lasfopciones deben ser las últimas porque el nombre del archivo sigue (tar xzf bar.tar.gzfunciona perotar xfz bar.tar.gzno funciona) este no es el caso aquí (ver los ejemplos posteriores).Múltiples opciones con argumentos
Como otra ventaja, los parámetros de las opciones se consumen en el orden de las opciones por los parámetros con las opciones requeridas. Solo mira la salida de mi script aquí con la línea de comando
abc X Y Z(o-abc X Y Z):Las opciones largas también se concatenan
Además, también puede tener opciones largas en el bloque de opciones dado que ocurren en último lugar en el bloque. Por lo tanto, las siguientes líneas de comando son todas equivalentes (incluido el orden en que se procesan las opciones y sus argumentos):
-cba Z Y Xcba Z Y X-cb-aaa-0-args Z Y X-c-bbb-1-args Z Y X -a--ccc-2-args Z Y -ba Xc Z Y b X a-c Z Y -b X -a--ccc-2-args Z Y --bbb-1-args X --aaa-0-argsTodos estos conducen a:
No en esta solución
Argumentos opcionales
Las opciones con argumentos opcionales deberían ser posibles con un poco de trabajo, por ejemplo, mirando hacia adelante si hay un bloque sin guión; el usuario necesitaría poner un guión delante de cada bloque después de un bloque con un parámetro que tenga un parámetro opcional. Tal vez esto sea demasiado complicado para comunicarse con el usuario, por lo que es mejor que solo requiera un guión principal en este caso.
Las cosas se vuelven aún más complicadas con múltiples parámetros posibles. Aconsejaría no hacer que las opciones intenten ser inteligentes al determinar si un argumento puede ser adecuado o no (por ejemplo, con una opción solo toma un número como argumento opcional) porque esto podría romperse en el futuro.
Personalmente, prefiero opciones adicionales en lugar de argumentos opcionales.
Opción argumentos introducidos con un signo igual
Al igual que con los argumentos opcionales, no soy fanático de esto (por cierto, ¿hay un hilo para discutir los pros / contras de los diferentes estilos de parámetros?) Pero si lo desea, probablemente podría implementarlo usted mismo como lo hizo en http: // mywiki.wooledge.org/BashFAQ/035#Manual_loop con un
--long-with-arg=?*enunciado de caso y luego quitando el signo igual (esto es, por cierto, el sitio que dice que es posible realizar la concatenación de parámetros con cierto esfuerzo, pero "lo dejó como un ejercicio para el lector "lo que me hizo tomarles la palabra pero empecé desde cero".Otras notas
Compatible con POSIX, funciona incluso en configuraciones antiguas de Busybox con las que tuve que lidiar (por ejemplo
cut,headygetoptsfalta).fuente