scripts script programas pasar parametros operaciones manejo example ejemplos cadenas aritmeticas bash shell getopts

script - Un ejemplo de cómo usar getopts en bash



script linux ejemplos (6)

El ejemplo empaquetado con getopt (mi distribución lo puso en /usr/share/getopt/getopt-parse.bash ) parece que cubre todos sus casos:

#!/bin/bash # A small example program for using the new getopt(1) program. # This program will only work with bash(1) # An similar program using the tcsh(1) script language can be found # as parse.tcsh # Example input and output (from the bash prompt): # ./parse.bash -a par1 ''another arg'' --c-long ''wow!*/?'' -cmore -b " very long " # Option a # Option c, no argument # Option c, argument `more'' # Option b, argument ` very long '' # Remaining arguments: # --> `par1'' # --> `another arg'' # --> `wow!*/?'' # Note that we use `"$@"'' to let each command-line parameter expand to a # separate word. The quotes around `$@'' are essential! # We need TEMP as the `eval set --'' would nuke the return value of getopt. TEMP=`getopt -o ab:c:: --long a-long,b-long:,c-long:: / -n ''example.bash'' -- "$@"` if [ $? != 0 ] ; then echo "Terminating..." >&2 ; exit 1 ; fi # Note the quotes around `$TEMP'': they are essential! eval set -- "$TEMP" while true ; do case "$1" in -a|--a-long) echo "Option a" ; shift ;; -b|--b-long) echo "Option b, argument /`$2''" ; shift 2 ;; -c|--c-long) # c has an optional argument. As we are in quoted mode, # an empty parameter will be generated if its optional # argument is not found. case "$2" in "") echo "Option c, no argument"; shift 2 ;; *) echo "Option c, argument /`$2''" ; shift 2 ;; esac ;; --) shift ; break ;; *) echo "Internal error!" ; exit 1 ;; esac done echo "Remaining arguments:" for arg do echo ''--> ''"/`$arg''" ; done

Quiero llamar myscript archivo myscript de esta manera:

$ ./myscript -s 45 -p any_string

o

$ ./myscript -h >>> should display help $ ./myscript >>> should display help

Mis requerimientos son:

  • getopt aquí para obtener los argumentos de entrada
  • compruebe que -s existe, si no devuelve error
  • compruebe que el valor después de la -s es 45 o 90
  • comprueba que existe -p y que hay una cadena de entrada después de
  • si el usuario ingresa ./myscript -h o simplemente ./myscript entonces muestra ayuda

He intentado hasta ahora este código:

#!/bin/bash while getopts "h:s:" arg; do case $arg in h) echo "usage" ;; s) strength=$OPTARG echo $strength ;; esac done

Pero con ese código me sale errores. ¿Cómo hacerlo con Bash y getopt ?


El problema con el código original es que:

  • h: espera el parámetro donde no debería, así que cámbielo a solo h (sin dos puntos)
  • para esperar -p any_string , debe agregar p: a la lista de argumentos

La sintaxis básica de getopts es (ver: man bash ):

getopts OPTSTRING VARNAME [ARGS...]

dónde:

  • OPTSTRING es una cadena con una lista de argumentos esperados,

    • h - verifique la opción -h sin parámetros; da error en opciones no soportadas;
    • h: - Verifique la opción -h con parámetro; da errores en opciones no soportadas;
    • abc - verifique las opciones -a , -b , -c ; da errores en opciones no soportadas;
    • :abc - verifique las opciones -a , -b , -c ; silencia los errores en opciones no soportadas;

      Notas: En otras palabras, dos puntos frente a las opciones le permite manejar los errores en su código. ¿La variable contendrá ? en el caso de una opción no compatible,: en el caso de un valor perdido.

  • OPTARG - se establece en el valor del argumento actual,

  • OPTERR : indica si Bash debe mostrar mensajes de error.

Entonces el código puede ser:

#!/usr/bin/env bash usage() { echo "$0 usage:" && grep " .)/ #" $0; exit 0; } [ $# -eq 0 ] && usage while getopts ":hs:p:" arg; do case $arg in p) # Specify p value. echo "p is ${OPTARG}" ;; s) # Specify strength, either 45 or 90. strength=${OPTARG} [ $strength -eq 45 -o $strength -eq 90 ] / && echo "Strength is $strength." / || echo "Strength needs to be either 45 or 90, $strength found instead." ;; h | *) # Display help. usage exit 0 ;; esac done

Ejemplo de uso:

$ ./foo.sh ./foo.sh usage: p) # Specify p value. s) # Specify strength, either 45 or 90. h | *) # Display help. $ ./foo.sh -s 123 -p any_string Strength needs to be either 45 or 90, 123 found instead. p is any_string $ ./foo.sh -s 90 -p any_string Strength is 90. p is any_string

Ver: tutorial de pequeños getopts en Bash Hackers Wiki


Sé que esto ya está respondido, pero para el registro y para cualquier persona con los mismos requisitos que yo, decidí publicar esta respuesta relacionada. El código está inundado de comentarios para explicar el código.

Respuesta actualizada:

Guarde el archivo como getopt.sh :

#!/bin/bash function get_variable_name_for_option { local OPT_DESC=${1} local OPTION=${2} local VAR=$(echo ${OPT_DESC} | sed -e "s/.*/[/?-${OPTION} /([A-Z_]/+/).*//1/g" -e "s/.*/[/?-/(${OPTION}/).*//1FLAG/g") if [[ "${VAR}" == "${1}" ]]; then echo "" else echo ${VAR} fi } function parse_options { local OPT_DESC=${1} local INPUT=$(get_input_for_getopts "${OPT_DESC}") shift while getopts ${INPUT} OPTION ${@}; do [ ${OPTION} == "?" ] && usage VARNAME=$(get_variable_name_for_option "${OPT_DESC}" "${OPTION}") [ "${VARNAME}" != "" ] && eval "${VARNAME}=${OPTARG:-true}" # && printf "/t%s/n" "* Declaring ${VARNAME}=${!VARNAME} -- OPTIONS=''$OPTION''" done check_for_required "${OPT_DESC}" } function check_for_required { local OPT_DESC=${1} local REQUIRED=$(get_required "${OPT_DESC}" | sed -e "s//://g") while test -n "${REQUIRED}"; do OPTION=${REQUIRED:0:1} VARNAME=$(get_variable_name_for_option "${OPT_DESC}" "${OPTION}") [ -z "${!VARNAME}" ] && printf "ERROR: %s/n" "Option -${OPTION} must been set." && usage REQUIRED=${REQUIRED:1} done } function get_input_for_getopts { local OPT_DESC=${1} echo ${OPT_DESC} | sed -e "s//([a-zA-Z]/) [A-Z_]/+//1:/g" -e "s/[][ -]//g" } function get_optional { local OPT_DESC=${1} echo ${OPT_DESC} | sed -e "s/[^[]*/(/[[^]]*/]/)[^[]*//1/g" -e "s//([a-zA-Z]/) [A-Z_]/+//1:/g" -e "s/[][ -]//g" } function get_required { local OPT_DESC=${1} echo ${OPT_DESC} | sed -e "s//([a-zA-Z]/) [A-Z_]/+//1:/g" -e "s//[[^[]*/]//g" -e "s/[][ -]//g" } function usage { printf "Usage:/n/t%s/n" "${0} ${OPT_DESC}" exit 10 }

Entonces puedes usarlo así:

#!/bin/bash # # [ and ] defines optional arguments # # location to getopts.sh file source ./getopt.sh USAGE="-u USER -d DATABASE -p PASS -s SID [ -a START_DATE_TIME ]" parse_options "${USAGE}" ${@} echo ${USER} echo ${START_DATE_TIME}

Respuesta antigua:

Hace poco necesité usar un enfoque genérico. Me encontré con esta solución:

#!/bin/bash # Option Description: # ------------------- # # Option description is based on getopts bash builtin. The description adds a variable name feature to be used # on future checks for required or optional values. # The option description adds "=>VARIABLE_NAME" string. Variable name should be UPPERCASE. Valid characters # are [A-Z_]*. # # A option description example: # OPT_DESC="a:=>A_VARIABLE|b:=>B_VARIABLE|c=>C_VARIABLE" # # -a option will require a value (the colon means that) and should be saved in variable A_VARIABLE. # "|" is used to separate options description. # -b option rule applies the same as -a. # -c option doesn''t require a value (the colon absense means that) and its existence should be set in C_VARIABLE # # ~$ echo get_options ${OPT_DESC} # a:b:c # ~$ # # Required options REQUIRED_DESC="a:=>REQ_A_VAR_VALUE|B:=>REQ_B_VAR_VALUE|c=>REQ_C_VAR_FLAG" # Optional options (duh) OPTIONAL_DESC="P:=>OPT_P_VAR_VALUE|r=>OPT_R_VAR_FLAG" function usage { IFS="|" printf "%s" ${0} for i in ${REQUIRED_DESC}; do VARNAME=$(echo $i | sed -e "s/.*=>//g") printf " %s" "-${i:0:1} $VARNAME" done for i in ${OPTIONAL_DESC}; do VARNAME=$(echo $i | sed -e "s/.*=>//g") printf " %s" "[-${i:0:1} $VARNAME]" done printf "/n" unset IFS exit } # Auxiliary function that returns options characters to be passed # into ''getopts'' from a option description. # Arguments: # $1: The options description (SEE TOP) # # Example: # OPT_DESC="h:=>H_VAR|f:=>F_VAR|P=>P_VAR|W=>W_VAR" # OPTIONS=$(get_options ${OPT_DESC}) # echo "${OPTIONS}" # # Output: # "h:f:PW" function get_options { echo ${1} | sed -e "s//([a-zA-Z]/:/?/)=>[A-Z_]*|/?//1/g" } # Auxiliary function that returns all variable names separated by ''|'' # Arguments: # $1: The options description (SEE TOP) # # Example: # OPT_DESC="h:=>H_VAR|f:=>F_VAR|P=>P_VAR|W=>W_VAR" # VARNAMES=$(get_values ${OPT_DESC}) # echo "${VARNAMES}" # # Output: # "H_VAR|F_VAR|P_VAR|W_VAR" function get_variables { echo ${1} | sed -e "s/[a-zA-Z]/:/?=>/([^|]*/)//1/g" } # Auxiliary function that returns the variable name based on the # option passed by. # Arguments: # $1: The options description (SEE TOP) # $2: The option which the variable name wants to be retrieved # # Example: # OPT_DESC="h:=>H_VAR|f:=>F_VAR|P=>P_VAR|W=>W_VAR" # H_VAR=$(get_variable_name ${OPT_DESC} "h") # echo "${H_VAR}" # # Output: # "H_VAR" function get_variable_name { VAR=$(echo ${1} | sed -e "s/.*${2}/:/?=>/([^|]*/).*//1/g") if [[ ${VAR} == ${1} ]]; then echo "" else echo ${VAR} fi } # Gets the required options from the required description REQUIRED=$(get_options ${REQUIRED_DESC}) # Gets the optional options (duh) from the optional description OPTIONAL=$(get_options ${OPTIONAL_DESC}) # or... $(get_options "${OPTIONAL_DESC}|${REQUIRED_DESC}") # The colon at starts instructs getopts to remain silent while getopts ":${REQUIRED}${OPTIONAL}" OPTION do [[ ${OPTION} == ":" ]] && usage VAR=$(get_variable_name "${REQUIRED_DESC}|${OPTIONAL_DESC}" ${OPTION}) [[ -n ${VAR} ]] && eval "$VAR=${OPTARG}" done shift $(($OPTIND - 1)) # Checks for required options. Report an error and exits if # required options are missing. # Using function version ... VARS=$(get_variables ${REQUIRED_DESC}) IFS="|" for VARNAME in $VARS; do [[ -v ${VARNAME} ]] || usage done unset IFS # ... or using IFS Version (no function) OLDIFS=${IFS} IFS="|" for i in ${REQUIRED_DESC}; do VARNAME=$(echo $i | sed -e "s/.*=>//g") [[ -v ${VARNAME} ]] || usage printf "%s %s %s/n" "-${i:0:1}" "${!VARNAME:=present}" "${VARNAME}" done IFS=${OLDIFS}

No probé esto aproximadamente, así que podría tener algunos errores allí.


Usa getopt

¿Por qué getopt?

Para analizar argumentos de línea de comandos elaborados para evitar confusiones y aclarar las opciones, estamos analizando para que el lector de los comandos pueda entender lo que está sucediendo.

¿Qué es getopt?

getopt se utiliza para dividir (analizar) las opciones en las líneas de comando para facilitar el análisis mediante procedimientos de shell y para verificar opciones legales. Utiliza las rutinas getopt(3) GNU para hacer esto.

getopt puede tener los siguientes tipos de opciones.

  1. Opciones sin valor
  2. opciones de par clave-valor

Nota: En este documento, durante la explicación de la sintaxis:

  • Cualquier cosa dentro de [] es un parámetro opcional en la sintaxis / ejemplos.
  • es un marcador de posición, lo que significa que debe sustituirse por un valor real.

¿CÓMO UTILIZAR getopt ?

Sintaxis: Primera Forma

getopt optstring parameters

Ejemplos:

# This is correct getopt "hv:t::" "-v 123 -t123" getopt "hv:t::" "-v123 -t123" # -v and 123 doesn''t have whitespace # -h takes no value. getopt "hv:t::" "-h -v123" # This is wrong. after -t can''t have whitespace. # Only optional params cannot have whitespace between key and value getopt "hv:t::" "-v 123 -t 123" # Multiple arguments that takes value. getopt "h:v:t::g::" "-h abc -v 123 -t21" # Multiple arguments without value # All of these are correct getopt "hvt" "-htv" getopt "hvt" "-h -t -v" getopt "hvt" "-tv -h"

Aquí h, v, t son las opciones y -h -v -t es cómo deben darse las opciones en la línea de comandos.

  1. ''h'' es una opción sin valor.
  2. ''v:'' implica que la opción -v tiene valor y es una opción obligatoria. '':'' significa que tiene un valor.
  3. ''t ::'' implica que la opción -t tiene valor pero es opcional. ''::'' significa opcional.

En param opcional, el valor no puede tener una separación de espacios en blanco con la opción. Por lo tanto, en el ejemplo "-t123", -t es la opción 123 es valor.

Sintaxis: Segunda Forma

getopt [getopt_options] [--] [optstring] [parameters]

Aquí después de getopt se divide en cinco partes

  • El comando en sí es decir getopt
  • El getopt_options, describe cómo analizar los argumentos. Opciones de un solo guión largo, opciones de doble guión.
  • -, separa las opciones getopt_options de las opciones que desea analizar y las opciones cortas permitidas
  • Las opciones cortas, se toma inmediatamente después - se encuentra. Al igual que la primera sintaxis del formulario.
  • Los parámetros, estas son las opciones que has pasado al programa. Las opciones que desea analizar y obtener los valores reales establecidos en ellos.

Ejemplos

getopt -l "name:,version::,verbose" -- "n:v::V" "--name=Karthik -version=5.2 -verbose"

Sintaxis: Tercera Forma

getopt [getopt_options] [-o options] [--] [optstring] [parameters]

Aquí después de getopt se divide en cinco partes

  • El comando en sí es decir getopt
  • El getopt_options, describe cómo analizar los argumentos. Opciones de un solo guión largo, opciones de doble guión.
  • Las opciones cortas es decir -o o --opciones. Al igual que la primera sintaxis del formulario, pero con la opción "-o" y antes de la "-" (doble guión).
  • -, separa las opciones getopt_options de las opciones que desea analizar y las opciones cortas permitidas
  • Los parámetros, estas son las opciones que has pasado al programa. Las opciones que desea analizar y obtener los valores reales establecidos en ellos.

Ejemplos

getopt -l "name:,version::,verbose" -a -o "n:v::V" -- "-name=Karthik -version=5.2 -verbose"

GETOPT_OPTIONS

getopt_options cambia la forma en que se analizan los parámetros de línea de comandos.

A continuación se presentan algunas de las opciones getopt_

Opción: -l o --opciones

El comando getopt significa que debe permitir el reconocimiento de opciones de múltiples caracteres. Las múltiples opciones están separadas por comas.

Por ejemplo, --name=Karthik es una opción larga que se envía en la línea de comandos. En getopt, el uso de opciones largas es como

getopt "name:,version" "--name=Karthik"

Como se especifica el nombre: la opción debe contener un valor

Opción: -a o - alternativa

El comando getopt significa que la opción larga debe tener un solo guión ''-'' en lugar del guión doble ''-''.

Ejemplo, en lugar de --name=Karthik puedes usar solo -name=Karthik

getopt "name:,version" "-name=Karthik"

Un ejemplo completo de script con el código:

#!/bin/bash # filename: commandLine.sh # author: @theBuzzyCoder showHelp() { # `cat << EOF` This means that cat should stop reading when EOF is detected cat << EOF Usage: ./installer -v <espo-version> [-hrV] Install Pre-requisites for EspoCRM with docker in Development mode -h, -help, --help Display help -v, -espo-version, --espo-version Set and Download specific version of EspoCRM -r, -rebuild, --rebuild Rebuild php vendor directory using composer and compiled css using grunt -V, -verbose, --verbose Run script in verbose mode. Will print out each step of execution. EOF # EOF is found above and hence cat command stops reading. This is equivalent to echo but much neater when printing out. } export version=0 export verbose=0 export rebuilt=0 # $@ is all command line parameters passed to the script. # -o is for short options like -v # -l is for long options with double dash like --version # the comma separates different long options # -a is for long options with single dash like -version options=$(getopt -l "help,version:,verbose,rebuild,dryrun" -o "hv:Vrd" -a -- "$@") # set --: # If no arguments follow this option, then the positional parameters are unset. Otherwise, the positional parameters # are set to the arguments, even if some of them begin with a ‘-’. eval set -- "$options" while true do case $1 in -h|--help) showHelp exit 0 ;; -v|--version) shift export version=$1 ;; -V|--verbose) export verbose=1 set -xv # Set xtrace and verbose mode. ;; -r|--rebuild) export rebuild=1 ;; --) shift break;; esac shift done

Ejecutando este archivo de script:

# With short options grouped together and long option # With double dash ''--version'' bash commandLine.sh --version=1.0 -rV # With short options grouped together and long option # With single dash ''-version'' bash commandLine.sh -version=1.0 -rV # OR with short option that takes value, value separated by whitespace # by key bash commandLine.sh -v 1.0 -rV # OR with short option that takes value, value without whitespace # separation from key. bash commandLine.sh -v1.0 -rV # OR Separating individual short options bash commandLine.sh -v1.0 -r -V


Ejemplo de POSIX 7

También vale la pena consultar el ejemplo del estándar: http://pubs.opengroup.org/onlinepubs/9699919799/utilities/getopts.html

aflag= bflag= while getopts ab: name do case $name in a) aflag=1;; b) bflag=1 bval="$OPTARG";; ?) printf "Usage: %s: [-a] [-b value] args/n" $0 exit 2;; esac done if [ ! -z "$aflag" ]; then printf "Option -a specified/n" fi if [ ! -z "$bflag" ]; then printf ''Option -b "%s" specified/n'' "$bval" fi shift $(($OPTIND - 1)) printf "Remaining arguments are: %s/n" "$*"

Y luego podemos probarlo:

$ sh a.sh Remaining arguments are: $ sh a.sh -a Option -a specified Remaining arguments are: $ sh a.sh -b No arg for -b option Usage: a.sh: [-a] [-b value] args $ sh a.sh -b myval Option -b "myval" specified Remaining arguments are: $ sh a.sh -a -b myval Option -a specified Option -b "myval" specified Remaining arguments are: $ sh a.sh remain Remaining arguments are: remain $ sh a.sh -- -a remain Remaining arguments are: -a remain

Probado en Ubuntu 17.10, sh es dash 0.5.8.


#!/bin/bash usage() { echo "Usage: $0 [-s <45|90>] [-p <string>]" 1>&2; exit 1; } while getopts ":s:p:" o; do case "${o}" in s) s=${OPTARG} ((s == 45 || s == 90)) || usage ;; p) p=${OPTARG} ;; *) usage ;; esac done shift $((OPTIND-1)) if [ -z "${s}" ] || [ -z "${p}" ]; then usage fi echo "s = ${s}" echo "p = ${p}"

Ejemplo de ejecución:

$ ./myscript.sh Usage: ./myscript.sh [-s <45|90>] [-p <string>] $ ./myscript.sh -h Usage: ./myscript.sh [-s <45|90>] [-p <string>] $ ./myscript.sh -s "" -p "" Usage: ./myscript.sh [-s <45|90>] [-p <string>] $ ./myscript.sh -s 10 -p foo Usage: ./myscript.sh [-s <45|90>] [-p <string>] $ ./myscript.sh -s 45 -p foo s = 45 p = foo $ ./myscript.sh -s 90 -p bar s = 90 p = bar