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

Voglio passare argomenti in esso.Argomenti di script di shelling

io sono abituato a fare $1, $2, $3 .... ma voglio iniziare a dar loro un nome

+2

Considerare non le opzioni di associazione ma il passaggio di valori attraverso l'ambiente: ad esempio "host = nomehost utente = me myscript.sh" –

+0

duplicato di http://stackoverflow.com/questions/192249/how-do-i-parse-command -line-arguments-in-bash, che ha una buona risposta confrontando pure-bash 'switch',' getopts' (built-in shell POSIX) e 'getopt' (non consigliato a meno che non sia la versione util-linux e tu ne usi la funzioni non POSIX per evitare problemi con argomenti vu, e così via.) –

risposta

13

Ci sono molti modi per analizzare argomenti in sh. Getopt è buono. Ecco un semplice script che analizza le cose a 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] 

Un esempio del suo funzionamento assomiglia:

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

Nota che questo non è neanche lontanamente robusta e massicciamente aperto alla sicurezza fori dal momento che una della eval sceneggiatura stringa costruita dall'utente. Si tratta semplicemente di destinato a servire da esempio per un possibile modo di fare le cose. Un metodo più semplice consiste nel richiedere all'utente di passare i dati nell'ambiente. In una Bourne shell (vale a dire, tutto ciò che non è nella famiglia csh):

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

funziona bene, e le variabili $host, $user, $pass sarà disponibile nello script.

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

L'uso di 'declare' invece di' eval' sarebbe più sicuro. –

+0

Oltre al suggerimento di @ DennisWilliamson, suggerisco di rimuovere '| tr -d '\ 012'', dato che non è necessario - la sostituzione del comando taglia automaticamente tutte le nuove righe finali. – mklement0

+0

@ mklement0 Credo che in realtà stavo pensando consapevolmente a newline interne, il che è strano considerando che il tentativo di affrontarlo è un tentativo di aggiungere robustezza a un'idea che è assurdamente fragile. Ci sono tanti modi in cui questo è fragile, è troppo divertente. –

9
+0

@Zac buona cattura, grazie. –

+1

Si noti che 'getopts' è un builtin di Bash mentre' getopt' è un'utilità esterna. Il primo funziona solo con opzioni brevi (ad esempio '-e') mentre quest'ultimo funzionerà anche con quelle lunghe (ad esempio' -foo'). Si noti che ci sono alcuni [problemi] (http://mywiki.wooledge.org/BashFAQ/035) con questi ultimi che devono essere affrontati (le versioni successive di 'getopt' hanno meno problemi). –

6

Ecco un modo semplice per gestire sia lunghe che corte opzioni:

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 

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

+1

+1; nota, tuttavia, che questo non gestirà le opzioni _compressed_, come '-vf' per rappresentare' -v -f'. – mklement0

0

adotto sopra William Pursell esempio (con la consulenza Dennis Williamson) per i parametri in questo formato : sceneggiatura -param1 = valore1 -param2 = valore2 ...

Ecco il codice con gli argomenti di una sola riga parser (salvarlo in file '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 

si chiamano così:

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

e il risultato è

host = aaa 
user = bbb 
pass = ccc 

Do qualcuno conoscere il codice più breve per analizzare argomenti di questo di cui sopra?

Problemi correlati