Tabla de contenidos

¿Desea que sus scripts de shell de Linux manejen las opciones y los argumentos de la línea de comandos con más gracia? El Bash getoptsincorporado le permite analizar las opciones de la línea de comandos con delicadeza, y también es fácil. Te mostramos cómo.
Presentamos el getopts incorporado
Pasar valores a un script Bash es bastante sencillo. Llama a su secuencia de comandos desde la línea de comando o desde otra secuencia de comandos y proporciona su lista de valores detrás del nombre de la secuencia de comandos. Se puede acceder a estos valores dentro de su secuencia de comandos como variables , comenzando con $1la primera variable, $2la segunda y así sucesivamente.
Pero si desea pasar opciones a un script, la situación rápidamente se vuelve más compleja. Cuando decimos opciones, nos referimos a las opciones, banderas o interruptores que lspueden manejar programas similares. Están precedidos por un guión “ -” y generalmente actúan como un indicador para que el programa active o desactive algún aspecto de su funcionalidad.
El lscomando tiene más de 50 opciones, principalmente relacionadas con el formato de su salida. La -Xopción (ordenar por extensión) ordena la salida alfabéticamente por extensión de archivo . La -Uopción (sin clasificar) enumera por orden de directorio .
Las opciones son solo eso, son opcionales. No sabe qué opciones, si las hay, elegirá usar el usuario, y tampoco sabe en qué orden puede enumerarlas en la línea de comando . Esto aumenta la complejidad del código necesario para analizar las opciones.
Las cosas se vuelven aún más complicadas si algunas de sus opciones toman un argumento, conocido como argumento de opción . Por ejemplo, la ls -wopción (ancho) espera ser seguida por un número, que representa el ancho máximo de visualización de la salida. Y, por supuesto, es posible que esté pasando otros parámetros a su secuencia de comandos que son simplemente valores de datos, que no son opciones en absoluto.
Afortunadamente getoptsmaneja esta complejidad por ti. Y debido a que está integrado, está disponible en todos los sistemas que tienen el shell Bash, por lo que no hay nada que instalar.
Nota: getopts No getopt
Hay una utilidad más antigua llamada getopt. Este es un pequeño programa de utilidad , no un incorporado. Hay muchas versiones diferentes de getoptcon diferentes comportamientos, mientras que el getopsincorporado sigue las pautas de POSIX.
escriba getopts
escriba getopt

Debido getopta que no es una función integrada, no comparte algunos de los beneficios automáticos que getopts sí tiene, como el manejo sensato de los espacios en blanco . Con getopts, el shell Bash está ejecutando su secuencia de comandos y el shell Bash está realizando el análisis de opciones. No necesita invocar un programa externo para manejar el análisis.
La compensación es getoptsque no maneja nombres de opciones de formato largo con guiones dobles. Por lo tanto, puede usar opciones formateadas como -w pero no «» ---wide-format. Por otro lado, si tiene un script que acepta las opciones -a, -by , -cgetoptsle permite combinarlas como -abc, -bcao -bacy así sucesivamente.
Estamos discutiendo y demostrando getopts en este artículo, así que asegúrese de agregar la «s» final al nombre del comando.
Un resumen rápido: manejo de valores de parámetros
Este script no usa opciones discontinuas como -ao -b. Acepta parámetros «normales» en la línea de comandos y se accede a ellos dentro del script como valores.
#!/bin/bash # obtener las variables una por una echo "Variable Uno: $1" echo "Variable Dos: $2" echo "Variable Tres: $3" # recorrer las variables para var en " $@" haz echo "$ var" hecho
Se accede a los parámetros dentro del script como variables $1, $2o $3.
Copie este texto en un editor y guárdelo como un archivo llamado «variables.sh». Tendremos que hacerlo ejecutable con el chmodcomando . Deberá realizar este paso para todos los scripts que discutimos. Simplemente sustituya el nombre del archivo de script apropiado cada vez.
chmod +x variables.sh

Si ejecutamos nuestro script sin parámetros, obtenemos este resultado.
./variables.sh

No pasamos parámetros, por lo que el script no tiene valores para informar. Proporcionemos algunos parámetros esta vez.
./variables.sh cómo geek

Como era de esperar, las variables $1, $2y $3se han establecido en los valores de los parámetros y los vemos impresos.
Este tipo de manejo de parámetros uno por uno significa que necesitamos saber de antemano cuántos parámetros habrá. Al bucle en la parte inferior del script no le importa cuántos parámetros hay, siempre los recorre todos.
Si proporcionamos un cuarto parámetro, no se asigna a una variable, pero el ciclo aún lo maneja.
./variables.sh cómo geek sitio web

Si ponemos comillas alrededor de dos de las palabras, se tratan como un parámetro.
./variables.sh cómo "ser geek"

Si vamos a necesitar que nuestro script maneje todas las combinaciones de opciones, opciones con argumentos y parámetros de tipo de datos «normales», necesitaremos separar las opciones de los parámetros regulares. Podemos lograr eso colocando todas las opciones, con o sin argumentos, antes de los parámetros regulares.
Pero no corramos antes de que podamos caminar. Veamos el caso más simple para manejar las opciones de la línea de comandos.
Opciones de manejo
Usamos getoptsen un whilebucle. Cada iteración del ciclo funciona en una opción que se pasó al script. En cada caso, la variable OPTIONse establece en la opción identificada por getopts.
Con cada iteración del bucle, getoptspasa a la siguiente opción. Cuando no hay más opciones, getoptsregresa falsey whilesale del bucle.
La OPTIONvariable se compara con los patrones en cada una de las cláusulas de declaración de caso. Debido a que estamos usando una declaración de caso , no importa en qué orden se proporcionen las opciones en la línea de comando. Cada opción se coloca en la declaración del caso y se activa la cláusula correspondiente.
Las cláusulas individuales en la declaración del caso facilitan la realización de acciones específicas de opciones dentro del script. Por lo general, en una secuencia de comandos del mundo real, establecería una variable en cada cláusula, y estos actuarían como indicadores más adelante en la secuencia de comandos, permitiendo o denegando alguna funcionalidad.
Copie este texto en un editor y guárdelo como un script llamado «options.sh» y hágalo ejecutable.
#!/bin/bash
mientras getopts 'abc' OPCIÓN; hacer
caso "$OPCIÓN" en
a)
echo "Opción a usada" ;;
B)
echo "Opción b usada"
;;
C)
echo "Opción c usada"
;;
?)
echo "Uso: $(nombre base $0) [-a] [-b] [-c]"
salida 1
;;
esac
hechoEsta es la línea que define el ciclo while.
mientras getopts 'abc' OPCIÓN; hacer
El getoptscomando va seguido de la cadena de opciones . Esto enumera las letras que vamos a usar como opciones. Solo las letras de esta lista se pueden utilizar como opciones. Entonces, en este caso, -dno sería válido. Esto quedaría atrapado por la ?)cláusula porque getoptsdevuelve un signo de interrogación “ ?” para una opción no identificada. Si eso sucede, el uso correcto se imprime en la ventana de la terminal:
echo "Uso: $(nombre base $0) [-a] [-b] [-c]"
Por convención, envolver una opción entre corchetes “ []” en este tipo de mensaje de uso correcto significa que la opción es opcional. El comando basename elimina cualquier ruta de directorio del nombre del archivo. El nombre del archivo de script se mantiene en los $0scripts de Bash.
Usemos este script con diferentes combinaciones de líneas de comando.
./opciones.sh -a
./opciones.sh -a -b -c
./opciones.sh -ab -c
./opciones.sh -taxi

Como podemos ver, todas nuestras combinaciones de prueba de opciones se analizan y manejan correctamente. ¿Y si probamos una opción que no existe?
./opciones.sh -d

Se activa la cláusula de uso, lo cual es bueno, pero también recibimos un mensaje de error del shell. Eso podría o no ser importante para su caso de uso. Si está llamando al script desde otro script que tiene que analizar mensajes de error, será más difícil si el shell también genera mensajes de error.
Desactivar los mensajes de error del shell es muy fácil. Todo lo que tenemos que hacer es poner dos puntos ” :” como el primer carácter de la cadena de opciones.
Edite su archivo «options.sh» y agregue dos puntos como el primer carácter de la cadena de opciones, o guarde este script como «options2.sh» y hágalo ejecutable.
#!/bin/bash
mientras que getopts ':abc' OPCIÓN; hacer
caso "$OPCIÓN" en
a)
echo "Opción a usada"
;;
B)
echo "Opción b usada"
;;
C)
echo "Opción c usada"
;;
?)
echo "Uso: $(nombre base $0) [-a] [-b] [-c]"
salida 1
;;
esac
hechoCuando ejecutamos esto y generamos un error, recibimos nuestros propios mensajes de error sin ningún mensaje de shell.
./opciones2.sh.sh -d

Uso de getopts con argumentos de opción
Para saber getoptsque una opción será seguida por un argumento, coloque dos puntos ” :” inmediatamente detrás de la letra de la opción en la cadena de opciones.
Si seguimos la «b» y la «c» en nuestra cadena de opciones con dos puntos, getoptesperará argumentos para estas opciones. Copie este script en su editor y guárdelo como «arguments.sh», y hágalo ejecutable.
Recuerde, los primeros dos puntos en la cadena de opciones se usan para suprimir los mensajes de error del shell; no tiene nada que ver con el procesamiento de argumentos.
Cuando getoptprocesa una opción con un argumento, el argumento se coloca en la OPTARGvariable. Si desea utilizar este valor en otra parte de su secuencia de comandos, deberá copiarlo en otra variable.
#!/bin/bash while getopts ':ab:c:' OPCIÓN; hacer caso "$OPCIÓN" en a) echo "Opción a usada" ;; B) argB="$OPTARG" echo "Opción b usada con: $argB" ;; C) argC="$OPTARG" echo "Opción c usada con: $argC" ;; ?) echo "Uso: $(nombre base $0) [-a] [-b argumento] [-c argumento]" salida 1 ;; esac hecho
Vamos a ejecutar eso y ver cómo funciona.
./argumentos.sh -a -b "cómo ser geek" -c reviewgeek
./argumentos.sh -c reviewgeek -a

Así que ahora podemos manejar opciones con o sin argumentos, independientemente del orden en que se presenten en la línea de comandos.
Pero, ¿qué pasa con los parámetros regulares? Anteriormente dijimos que sabíamos que tendríamos que ponerlos en la línea de comando después de cualquier opción. A ver qué pasa si lo hacemos.
Opciones y parámetros de mezcla
Cambiaremos nuestro script anterior para incluir una línea más. Cuando el whileciclo haya salido y todas las opciones hayan sido manejadas, intentaremos acceder a los parámetros regulares. Imprimiremos el valor en $1.
Guarde este script como «arguments2.sh» y hágalo ejecutable.
#!/bin/bash while getopts ':ab:c:' OPCIÓN; hacer caso "$OPCIÓN" en a) echo "Opción a usada" ;; B) argB="$OPTARG" echo "Opción b usada con: $argB" ;; C) argC="$OPTARG" echo "Opción c usada con: $argC" ;; ?) echo "Uso: $(nombre base $0) [-a] [-b argumento] [-c argumento]" salida 1 ;; esac hecho echo "La variable uno es: $1"
Ahora probaremos algunas combinaciones de opciones y parámetros.
./argumentos2.sh dave
./argumentos2.sh -a dave
./argumentos2.sh -a -c cómo-ser-geek dave

Así que ahora podemos ver el problema. Tan pronto como se utilizan las opciones, las variables $1en adelante se rellenan con los indicadores de opciones y sus argumentos. En el último ejemplo, $4mantendría el valor del parámetro «dave», pero ¿cómo accede a eso en su secuencia de comandos si no sabe cuántas opciones y argumentos se van a usar?
La respuesta es usar OPTINDy el shiftcomando.
El shiftcomando descarta el primer parámetro, independientemente del tipo, de la lista de parámetros. Los otros parámetros se “rebajan aleatoriamente”, por lo que el parámetro 2 se convierte en el parámetro 1, el parámetro 3 se convierte en el parámetro 2, y así sucesivamente. Y así $2se vuelve $1, $3se vuelve $2, y así sucesivamente.
Si proporciona shiftun número, eliminará esa cantidad de parámetros de la lista.
OPTINDcuenta las opciones y los argumentos a medida que se encuentran y procesan. Una vez que se hayan procesado todas las opciones y argumentos, OPTINDserá uno más que el número de opciones. Entonces, si usamos shift para recortar (OPTIND-1)parámetros de la lista de parámetros, nos quedaremos con los parámetros regulares en $1adelante.
Eso es exactamente lo que hace este script. Guarde este script como «arguments3.sh» y hágalo ejecutable.
#!/bin/bash
while getopts ':ab:c:' OPCIÓN; hacer
caso "$OPCIÓN" en
a)
echo "Opción a usada"
;;
B)
argB="$OPTARG"
echo "Opción b usada con: $argB"
;;
C)
argC="$OPTARG"
echo "Opción c usada con: $argC"
;;
?)
echo "Uso: $(nombre base $0) [-a] [-b argumento] [-c argumento]"
salida 1
;;
esac
hecho
echo "Antes - la variable uno es: $1"
cambio "$(($OPTIND -1))"
echo "Después - la variable uno es: $1"
echo "El resto de los argumentos (operandos)"
para x en "$@"
hacer
eco $x
hechoLo ejecutaremos con una combinación de opciones, argumentos y parámetros.
./arguments3.sh -a -c how-to-geek "dave dee" dozy beaky mick tich

Podemos ver que antes de llamar a shift, $1mantuvimos «-a», pero después de que el comando shift $1mantiene nuestro primer parámetro sin opción ni argumento. Podemos recorrer todos los parámetros tan fácilmente como en un script sin análisis de opciones.
Siempre es bueno tener opciones
El manejo de opciones y sus argumentos en scripts no tiene por qué ser complicado. Con getoptsusted puede crear secuencias de comandos que manejen opciones, argumentos y parámetros de la línea de comandos exactamente como deberían hacerlo las secuencias de comandos nativas compatibles con POSIX.