Getopt es una función de la biblioteca C que se utiliza para analizar opciones de línea de comandos del estilo Unix/POSIX. Forma parte de la especificación POSIX y es universal para sistemas tipo Unix . También es el nombre de un programa Unix para analizar argumentos de línea de comandos en scripts de shell.
Un problema de larga data con los programas de línea de comandos era cómo especificar opciones; los primeros programas usaban muchas formas de hacerlo, incluidas opciones de un solo carácter ( -a
), opciones múltiples especificadas juntas ( -abc
es equivalente a -a -b -c
), opciones de múltiples caracteres ( -inum
), opciones con argumentos ( -a arg
, -inum 3
, -a=arg
) y diferentes caracteres de prefijo ( -a
, +b
, /c
).
La función getopt se escribió para que fuera un mecanismo estándar que todos los programas pudieran usar para analizar las opciones de la línea de comandos , de modo que hubiera una interfaz común de la que todos pudieran depender. Por ello, los autores originales seleccionaron entre las variaciones la compatibilidad con opciones de un solo carácter, opciones múltiples especificadas juntas y opciones con argumentos ( o ), todas controlables mediante una cadena de opciones.-a arg
-aarg
getopt se remonta al menos a 1980 [1] y fue publicado por primera vez por AT&T en la conferencia UNIFORUM de 1985 en Dallas, Texas, con la intención de que estuviera disponible en el dominio público. [2] Posteriormente, otras versiones de este fueron adoptadas por otros tipos de Unix ( 4.3BSD , Linux , etc.). Se especifica en el estándar POSIX.2 como parte del archivo de encabezado unistd.h . Se han creado derivados de getopt para muchos lenguajes de programación para analizar las opciones de la línea de comandos.
Una función complementaria estándar de POSIX para getopt
[3] es getsubopt
. [4] Analiza una cadena de subopciones separadas por comas. Apareció en 4.4BSD (1995). [5]
getopt es una función que depende del sistema y su comportamiento depende de la implementación en la biblioteca C. Sin embargo, existen algunas implementaciones personalizadas como gnulib . [6]
El manejo convencional (POSIX y BSD) es que las opciones terminan cuando se encuentra el primer argumento que no es una opción, y que getopt devolvería -1 para señalarlo. Sin embargo, en la extensión glibc , las opciones se permiten en cualquier lugar para facilitar su uso; getopt permuta implícitamente el vector de argumentos de modo que aún deja las opciones no válidas al final. Dado que POSIX ya tiene la convención de devolver -1 y omitirlo, siempre se puede utilizar de forma portable como un significante de fin de opciones. [6]--
Una extensión GNU , getopt_long , permite el análisis de opciones multicarácter más legibles, que se introducen con dos guiones en lugar de uno. La elección de dos guiones permite --inum
diferenciar las opciones multicarácter ( ) de las opciones de un solo carácter especificadas juntas ( -abc
). La extensión GNU también permite un formato alternativo para las opciones con argumentos: --name=arg
. [6] Esta interfaz resultó popular y ha sido adoptada (sin la permutación) por muchas distribuciones BSD, incluyendo FreeBSD y Solaris . [7] Una forma alternativa de soportar opciones largas se ve en Solaris y Korn Shell (extendiendo optstring ), pero no fue tan popular. [8]
Otra extensión avanzada común de getopt es restablecer el estado del análisis de argumentos; esto es útil como reemplazo de la extensión GNU options-anyware, o como una forma de "superponer" un conjunto de interfaces de línea de comandos con diferentes opciones en diferentes niveles. Esto se logra en sistemas BSD utilizando una variable optreset , y en sistemas GNU configurando optind a 0. [6]
La sintaxis de línea de comandos para los programas basados en getopt es la sintaxis de argumentos de utilidad recomendada por POSIX. En resumen: [9]
-
carácter (guión-menos).:
después del nombre de la opción (solo durante la especificación inicial)o
toma un argumento, -ofoo
es lo mismo que -o foo
.a
y b
no toman argumentos mientras que e
toma un argumento opcional, -abe
es lo mismo que -a -b -e
, pero -bea
no es lo mismo que -b -e a
debido a la regla anterior.--
siempre marca el final de las opciones.Las extensiones de la sintaxis incluyen la convención GNU y la especificación CLIP de Sun. [10] [11]
El manual getopt de GNU especifica dicho uso para getopt: [12]
#include <unistd.h> int getopt ( int argc , char * const argv [], const char * optstring );
Aquí argc y argv se definen exactamente como en el prototipo de la función principal de C ; es decir, argc indica la longitud de la matriz de cadenas argv. La cadena optstring contiene una especificación de qué opciones buscar (alfabetos normales excepto W ) y qué opciones aceptar como argumentos (dos puntos). Por ejemplo, "vf::o:" se refiere a tres opciones: una v sin argumentos, una f con argumentos opcionales y una o con argumentos obligatorios . GNU implementa aquí una extensión W para sinónimos de opciones largas. [12]
getopt devuelve un entero que puede ser un carácter de opción o -1 para el final de las opciones. [12] El modismo consiste en utilizar un bucle while para recorrer las opciones y utilizar una declaración switch-case para seleccionar y actuar sobre las opciones. Consulte la sección de ejemplos de este artículo.
Para comunicar información adicional al programa, extern
el programa hace referencia a algunas variables globales para obtener información de getopt
:
extern char * optarg ; extern int optind , opterr , optopt ;
La interfaz getopt_long de la extensión GNU es similar, aunque pertenece a un archivo de encabezado diferente y toma una opción adicional para definir los nombres "cortos" de las opciones largas y algunos controles adicionales. Si no se define un nombre corto, getopt colocará un índice que haga referencia a la estructura de la opción en el puntero longindex . [12]
#incluir <getopt.h> int getopt_long ( int argc , char * const argv [], const char * optstring , const struct option * longopts , int * longindex );
#include <stdio.h> /* para printf */ #include <stdlib.h> /* para salir */ #include <unistd.h> /* para getopt */ int main ( int argc , char ** argv ) { int c ; int digit_optind = 0 ; int aopt = 0 , bopt = 0 ; char * copt = 0 , * dopt = 0 ; mientras (( c = getopt ( argc , argv , "abc:d:012" )) != -1 ) { int esta_opcion_optind = optind ? optind : 1 ; switch ( c ) { case '0' : case '1' : case '2' : if ( digit_optind != 0 && digit_optind != this_option_optind ) { printf ( "los dígitos aparecen en dos elementos argv diferentes. \n " ); } digit_optind = this_option_optind ; printf ( "opción %c \n " , c ); break ; case 'a' : printf ( "opción a \n " ); aopt = 1 ; break ; case 'b' : printf ( "opción b \n " ); bopt = 1 ; break ; case 'c' : printf ( "opción c con valor '%s' \n " , optarg ); copt = optarg ; break ; case 'd' :printf ( "opción d con valor '%s' \n " , optarg ); dopt = optarg ; break ; case '?' : break ; default : printf ( "?? getopt devolvió el código de carácter 0%o ?? \n " , c ); } } if ( optind < argc ) { printf ( "elementos ARGV no opcionales: " ); while ( optind < argc ) { printf ( "%s " , argv [ optind ++ ]); } printf ( " \n " ); } exit ( 0 ); }
#include <stdio.h> /* para printf */ #include <stdlib.h> /* para salir */ #include <getopt.h> /* para getopt_long; El estándar POSIX getopt está en unistd.h */ int main ( int argc , char ** argv ) { int c ; int digit_optind = 0 ; int aopt = 0 , bopt = 0 ; char * copt = 0 , * dopt = 0 ; int option_index = 0 ; estructura estática opción opciones_largas [] = { /* NOMBRE ARGUMENTO BANDERA NOMBRE_CORTOO */ { "agregar" , argumento_obligatorio , NULL , 0 }, { "agregar" , sin_argumento , NULL , 0 } , { " eliminar " , argumento_obligatorio , NULL , 0 }, { "verbose" , sin_argumento , NULL , 0 }, { "crear" , argumento_obligatorio , NULL , 'c' }, { "archivo" , argumento_obligatorio , NULL , 0 }, { NULL , 0 , NULL , 0 } }; int option_index = 0 ; mientras (( c = getopt_long ( argc , argv , "abc:d:012" , opciones_largas , & índice_opción )) != -1 ) { int esta_opción_optind = optind ? optind : 1 ; switch ( c ) { caso 0 : printf ( "opción %s" , opciones_largas [ índice_opción ]. nombre ); if ( optarg ) { printf ( " con arg %s" , optarg ); } printf ( " \n " ); break ; case '0' : case '1' : case '2' : if ( digit_optind != 0 && digit_optind != this_option_optind ) { printf ( "los dígitos aparecen en dos elementos argv diferentes. \n " ); } digit_optind = this_option_optind ; printf ( "opción %c \n " , c ); break ; case 'a' : printf ( "opción a \n " ); aopt = 1 ; break ; case 'b' : printf ( "opción b \n " ); bopt = 1 ; break ; case 'c' : printf ( "opción c con valor '%s' \n " , optarg ); copt = optarg ; break ; caso 'd' : printf ( "opción d con valor '%s' \n " , optarg ); dopt = optarg ; break ; caso '?' : break ; predeterminado : printf ( "?? getopt devolvió el código de carácter 0%o ?? \n " , c ); } } if ( optind < argc ) { printf ( "elementos ARGV que no son opciones: " ); while ( optind < argc ) { printf ( "%s " ,argv [ optind ++ ]); } printf ( " \n " ); } salir ( 0 ); }
Los programadores de scripts de shell suelen querer ofrecer una forma coherente de proporcionar opciones. Para lograr este objetivo, recurren a getopts y buscan adaptarlo a su propio lenguaje.
El primer intento de portabilidad fue el programa getopt , implementado por Unix System Laboratories (USL). Esta versión no podía manejar comillas ni metacaracteres de shell, ya que no mostraba intentos de comillas. FreeBSD la heredó. [13]
En 1986, USL decidió que no era aceptable seguir siendo inseguro con metacaracteres y espacios en blanco, y en su lugar creó el comando getopts incorporado para Bourne Shell de Unix SVR3. La ventaja de incorporar el comando en el shell es que ahora tiene acceso a las variables del shell, por lo que los valores se pueden escribir de forma segura sin comillas. Utiliza las propias variables del shell para rastrear la posición de las posiciones actuales y de los argumentos, OPTIND y OPTARG , y devuelve el nombre de la opción en una variable del shell.
En 1995, getopts
se incluyó en la versión 1 de la Especificación Única de UNIX / X/Open Portability Guidelines Issue 4. [14] Ahora como parte del estándar POSIX Shell, getopts se ha extendido por todas partes en muchos otros shells que intentan ser compatibles con POSIX.
getopt quedó básicamente en el olvido hasta que util-linux lanzó una versión mejorada que solucionaba todos los problemas del antiguo getopt mediante el escape. También admite los nombres de opciones largos de GNU. [15] Por otro lado, las opciones largas se han implementado rara vez en el getopts
comando en otros shells, siendo ksh93 una excepción.
getopt es una descripción concisa de la estructura de argumentos del comando POSIX común, y es ampliamente replicada por programadores que buscan proporcionar una interfaz similar, tanto para ellos mismos como para el usuario en la línea de comandos.
getopt
en la biblioteca C, pero se pueden usar gnulib [6] y MinGW (ambos aceptan el estilo GNU), así como algunas bibliotecas más mínimas, para proporcionar la funcionalidad. [16] También existen interfaces alternativas:popt
biblioteca, utilizada por el administrador de paquetes RPM , tiene la ventaja adicional de ser reentrante .argp
familia de funciones de glibc y gnulib proporciona más comodidad y modularidad.flag
paquete [17] que permite nombres de indicadores largos. El getopt
paquete [18] admite un procesamiento más cercano a la función C. También hay otro getopt
paquete [19] que proporciona una interfaz mucho más cercana a la POSIX original.{{cite web}}
: CS1 maint: others (link)