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

Chcę przekazać do niego argumenty.Parsowanie argumentów skryptu powłoki

jestem przyzwyczajony do robienia $1, $2, $3 .... ale chcę zacząć nazywania ich

+2

Należy uwzględnić opcje nieparowania, ale przekazywanie wartości przez środowisko: np. "Host = nazwa_hosta użytkownik = ja myscript.sh" –

+0

duplikat http://stackoverflow.com/questions/192249/how-do-i-parse-command -line-arguments-in-bash, który ma bardzo dobrą odpowiedź porównując czysto-bash 'switch',' getopts' (wbudowane powłoki POSIX) i 'getopt' (niezalecane, chyba że jest wersją util-linux i używasz jej funkcje inne niż POSIX, aby uniknąć problemów z pustymi argumentami itp.) –

Odpowiedz

13

Istnieje wiele sposobów analizowania argumentów w sh. Getopt jest dobry. Oto prosty skrypt, który analizuje rzeczy ręcznie:

#!/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] 

Trasa próbka wygląda następująco:

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

Należy pamiętać, że nie jest to nawet zdalnie wytrzymałe i masowo otwarty dla bezpieczeństwa otwory od skrypcie eval to ciąg skonstruowany przez użytkownika. Jest to po prostu mające służyć jako przykład dla jednego możliwego sposobu robienia rzeczy. Prostszą metodą jest wymaganie od użytkownika przekazywania danych w środowisku. W powłoce Bourne'a (czyli wszystko co nie mieści się w csh rodziny):

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

działa ładnie, a zmienne $host, $user, $pass będzie dostępna w skrypcie.

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

Użycie opcji 'declare' zamiast' eval' będzie bezpieczniejsze. –

+0

Oprócz sugestii @ DennisWilliamson sugeruję usunięcie '| tr -d '\ 012'', ponieważ nie jest to konieczne - podstawianie poleceń automatycznie przycina wszystkie końcowe znaki nowej linii. – mklement0

+0

@ mklement0 Wierzę, że faktycznie myślałem o wewnętrznych liniach, co jest dziwne, biorąc pod uwagę, że próba radzenia sobie z tym jest próbą dodania solidności do idei, która jest absurdalnie delikatna. Jest wiele sposobów, które są kruche, po prostu zbyt zabawne. –

9
+0

@Zac dobry połów, dzięki. –

+1

Zauważ, że 'getopts' jest wbudowanym Bashem, podczas gdy' getopt' jest zewnętrznym narzędziem. Ten pierwszy działa tylko z krótkimi opcjami (na przykład '-e'), podczas gdy drugi będzie działał również z długimi (np.' -foo'). Zauważ, że istnieją pewne problemy (http://mywiki.wooledge.org/BashFAQ/035) z tymi ostatnimi, które należy rozwiązać (nowsze wersje 'getopt' mają mniej problemów). –

6

Oto prosty sposób obsługiwać zarówno długie i krótkie opcje:

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 

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

+1

+1; zwróć jednak uwagę, że to nie będzie obsługiwać opcji _compressed_, takich jak '-vf', które reprezentują' -v -f'. – mklement0

0

ja przyjąć powyższy przykład William Pursell (z radą Dennis Williamson) dla parametrów w tym formacie : skrypt -param1 = wartość1 -param2 = wartość2 ...

Oto kod z jednoliniowym analizatorem argumentów (zapisz go w pliku "skrypt") :

#!/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 

to nazwać tak:

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

i wynik jest

host = aaa 
user = bbb 
pass = ccc 

Czy ktoś wie krótszy kod do analizowania argumentów niż ten powyżej?

Powiązane problemy