2011-02-03 29 views
8
$myscript.sh -host blah -user blah -pass blah 

Quiero pasarle argumentos.Analizando los argumentos del script de shell

que estoy acostumbrado a hacer $1, $2, $3 .... pero quiero empezar a nombrarlos

+2

Considere no pegar opciones pero pasar valores a través del entorno: por ejemplo, "host = nombre de host usuario = me myscript.sh" –

+0

duplicado de http://stackoverflow.com/questions/192249/how-do-i-parse-command -line-arguments-in-bash, que tiene una muy buena respuesta comparando pure-bash 'switch',' getopts' (POSIX shell builtin), y 'getopt' (no recomendado a menos que sea la versión de util-linux y use su características no POSIX para evitar problemas con args vacíos, etc.) –

Respuesta

13

Hay un montón de maneras de analizar los argumentos en sh. Getopt es bueno. He aquí un simple script que analiza las cosas con la mano:

#!/bin/sh 

while echo $1 | grep -q ^-; do 
    eval $(echo $1 | sed 's/^-//')=$2 
    shift 
    shift 
done 

echo host = $host 
echo user = $user 
echo pass = $pass 
echo args = [email protected] 

Una muestra de ejecución se parece a:

$ ./a.sh -host foo -user me -pass secret some args 
host = foo 
user = me 
pass = secret 
args = some args 

Tenga en cuenta que esto no es ni remotamente robusta y masivamente abierta a la seguridad agujeros ya que una de la eval guión cuerda construida por el usuario. Es simplemente destinado a servir como un ejemplo de una posible forma de hacer las cosas. Un método más simple es exigir al usuario que pase los datos en el entorno. En una cáscara de Bourne (es decir, cualquier cosa que no está en la familia CSH):

$ host=blah user=blah pass=blah myscript.sh 

funciona muy bien, y las variables $host, $user, $pass estará disponible en el guión.

#!/bin/sh 
echo host = ${host:?host empty or unset} 
echo user = ${user?user not set} 
... 
+2

Usar 'declare' en lugar de' eval' sería más seguro. –

+0

Además de la sugerencia de @ DennisWilliamson, sugiero eliminar '| tr -d '\ 012'', ya que no es necesario: la sustitución de comando recorta automáticamente todas las nuevas líneas finales. – mklement0

+0

@ mklement0 Creo que en realidad estaba pensando conscientemente en nuevas líneas internas, lo cual es extraño considerando que tratar de lidiar con eso es un intento de agregar robustez a una idea que es absurdamente frágil. Hay muchas formas en que esto es frágil, es demasiado gracioso. –

9
+0

@Zac buena captura, gracias. –

+1

Tenga en cuenta que 'getopts' es un Bash incorporado mientras que' getopt' es una utilidad externa. El primero solo funciona con opciones cortas (por ejemplo '-e') mientras que el último también funcionará con opciones largas (por ejemplo' -foo'). Tenga en cuenta que hay algunos [problemas] (http://mywiki.wooledge.org/BashFAQ/035) con los últimos que deben abordarse (las versiones posteriores de 'getopt' tienen menos problemas). –

6

Aquí es una forma sencilla de manejar tanto largas como cortas opciones:

while [[ $1 == -* ]]; do 
    case "$1" in 
     -h|--help|-\?) show_help; exit 0;; 
     -v|--verbose) verbose=1; shift;; 
     -f) if (($# > 1)); then 
      output_file=$2; shift 2 
      else 
      echo "-f requires an argument" 1>&2 
      exit 1 
      fi ;; 
     --) shift; break;; 
     -*) echo "invalid option: $1" 1>&2; show_help; exit 1;; 
    esac 
done 

Desde How can I handle command-line arguments (options) to my script easily?

+1

+1; tenga en cuenta, sin embargo, que esto no manejará _compressed_ options, como '-vf' para representar' -v -f'. – mklement0

0

adopto ejemplo anterior William Pursell (con el asesoramiento Dennis Williamson) para los parámetros en este formato : script -param1 = value1 -param2 = value2 ...

Aquí está el código con el analizador de argumentos de una sola línea (guárdelo en el archivo 'script') :

#!/bin/bash 

while echo $1 | grep ^- > /dev/null; do declare $(echo $1 | sed 's/-//g' | sed 's/=.*//g' | tr -d '\012')=$(echo $1 | sed 's/.*=//g' | tr -d '\012'); shift; done 

echo host = $host 
echo user = $user 
echo pass = $pass 

Se llaman así:

script -host=aaa -user=bbb -pass=ccc

y el resultado es

host = aaa 
user = bbb 
pass = ccc 

No sabe alguien código más corto para analizar los argumentos que esto arriba?

Cuestiones relacionadas