getopty getoptsson diferentes bestias, y las personas parecen tener un poco de incomprensión de lo que hacen. getoptses un comando incorporado bashpara procesar las opciones de la línea de comandos en un bucle y asignar cada opción y valor encontrados a su vez a las variables incorporadas, para que pueda procesarlas aún más. getopt, sin embargo, es un programa de utilidad externo, y en realidad no procesa sus opciones para usted de la manera en que lo hacen, por ejemplo getopts, bash , el Getoptmódulo Perl o Python optparse/ argparsemodules. Todo lo que getopthace es canonizar las opciones que se pasan, es decir, convertirlas a una forma más estándar, para que sea más fácil para un script de shell procesarlas. Por ejemplo, una aplicación de getoptpodría convertir lo siguiente:
myscript -ab infile.txt -ooutfile.txt
dentro de esto:
myscript -a -b -o outfile.txt infile.txt
Tienes que hacer el procesamiento real tú mismo. No tiene que usarlo getopten absoluto si establece varias restricciones en la forma en que puede especificar opciones:
- solo pon una opción por argumento;
- todas las opciones van antes que cualquier parámetro posicional (es decir, argumentos sin opciones);
- para opciones con valores (por ejemplo,
-oarriba), el valor debe ir como un argumento separado (después de un espacio).
¿Por qué usar en getoptlugar de getopts? La razón básica es que solo GNU getoptle brinda soporte para las opciones de línea de comandos de nombre largo. 1 (GNU getoptes el valor predeterminado en Linux. Mac OS X y FreeBSD vienen con una getoptversión básica y no muy útil , pero la versión GNU se puede instalar; ver más abajo).
Por ejemplo, aquí hay un ejemplo del uso de GNU getopt, de un script mío llamado javawrap:
# NOTE: This requires GNU getopt. On Mac OS X and FreeBSD, you have to install this
# separately; see below.
TEMP=`getopt -o vdm: --long verbose,debug,memory:,debugfile:,minheap:,maxheap: \
-n 'javawrap' -- "$@"`
if [ $? != 0 ] ; then echo "Terminating..." >&2 ; exit 1 ; fi
# Note the quotes around `$TEMP': they are essential!
eval set -- "$TEMP"
VERBOSE=false
DEBUG=false
MEMORY=
DEBUGFILE=
JAVA_MISC_OPT=
while true; do
case "$1" in
-v | --verbose ) VERBOSE=true; shift ;;
-d | --debug ) DEBUG=true; shift ;;
-m | --memory ) MEMORY="$2"; shift 2 ;;
--debugfile ) DEBUGFILE="$2"; shift 2 ;;
--minheap )
JAVA_MISC_OPT="$JAVA_MISC_OPT -XX:MinHeapFreeRatio=$2"; shift 2 ;;
--maxheap )
JAVA_MISC_OPT="$JAVA_MISC_OPT -XX:MaxHeapFreeRatio=$2"; shift 2 ;;
-- ) shift; break ;;
* ) break ;;
esac
done
Esto le permite especificar opciones como --verbose -dm4096 --minh=20 --maxhe 40 --debugfi="/Users/John Johnson/debug.txt"o similar. El efecto de la llamada a getoptes canonizar las opciones para --verbose -d -m 4096 --minheap 20 --maxheap 40 --debugfile "/Users/John Johnson/debug.txt"que pueda procesarlas más fácilmente. La cita alrededor "$1"y"$2" es importante ya que garantiza que los argumentos con espacios en ellos se manejen correctamente.
Si elimina las primeras 9 líneas (todo a través de la eval setlínea), ¡el código seguirá funcionando ! Sin embargo, su código será mucho más exigente en el tipo de opciones que acepta: en particular, tendrá que especificar todas las opciones en el formulario "canónico" descrito anteriormente. Sin getoptembargo, con el uso de , puede agrupar opciones de una sola letra, usar formas más cortas y no ambiguas de opciones largas, usar el estilo --file foo.txto --file=foo.txt, usar el estilo -m 4096o -m4096, mezclar opciones y no opciones en cualquier orden, etc. getopttambién genera un mensaje de error si se encuentran opciones no reconocidas o ambiguas.
NOTA : En realidad, hay dos versiones totalmente diferentes de getopt, basic getopty GNU getopt, con diferentes características y diferentes convenciones de llamadas. 2 Basic getoptestá bastante roto: no solo no maneja opciones largas, sino que ni siquiera puede manejar espacios incrustados dentro de argumentos o argumentos vacíos, mientras getoptsque lo hace bien. El código anterior no funcionará en básico getopt. GNU getoptse instala por defecto en Linux, pero en Mac OS X y FreeBSD necesita instalarse por separado. En Mac OS X, instale MacPorts ( http://www.macports.org ) y luego sudo port install getoptinstale GNU getopt(generalmente en /opt/local/bin), y asegúrese de que /opt/local/binesté en su ruta de shell antes de/usr/bin . En FreeBSD, instalemisc/getopt.
Una guía rápida para modificar el código de ejemplo para su propio programa: de las primeras líneas, todas son "repetitivas" que deben permanecer igual, excepto la línea que llama getopt. Debe cambiar el nombre del programa después -n, especificar opciones cortas después -oy opciones largas después --long. Poner dos puntos después de las opciones que toman un valor.
Finalmente, si ve un código que tiene solo en setlugar de eval set, fue escrito para BSD getopt. Debe cambiarlo para usar el eval setestilo, que funciona bien con ambas versiones de getopt, mientras que el plano setno funciona bien con GNU getopt.
1 En realidad, getoptsen ksh93soportes opciones nombrado largo, pero esta capa no se utiliza tan a menudo como bash. En zsh, use zparseoptspara obtener esta funcionalidad.
2 Técnicamente, "GNU getopt" es un nombre inapropiado; Esta versión fue escrita para Linux en lugar del proyecto GNU. Sin embargo, sigue todas las convenciones de GNU, y el término "GNU getopt" se usa comúnmente (por ejemplo, en FreeBSD).