$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
$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
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}
...
Użycie opcji 'declare' zamiast' eval' będzie bezpieczniejsze. –
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
@ 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. –
@Zac dobry połów, dzięki. –
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). –
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; zwróć jednak uwagę, że to nie będzie obsługiwać opcji _compressed_, takich jak '-vf', które reprezentują' -v -f'. – mklement0
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?
Należy uwzględnić opcje nieparowania, ale przekazywanie wartości przez środowisko: np. "Host = nazwa_hosta użytkownik = ja myscript.sh" –
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.) –