2012-02-14 14 views
10

Wszystko, co widzę, używa getopt lub nieco bardziej wyszukanego getopts, który obsługuje tylko opcje jednoliterowe (np. -h, ale nie --help). Chcę robić fantazyjne długie opcje.Jak mogę analizować długie argumenty w powłoce?

+1

możliwy duplikat [Używanie getopts w skrypcie powłoki bash do uzyskiwania długich i krótkich opcji wiersza poleceń] (http://stackoverflow.com/questions/402377/using-getopts-in-bash-shell-script-to-get -long-and-short-command-line-options-options) –

+1

@ JonathanLeffler Naprawdę nie jest duplikatem, ponieważ 'getops' nie zawsze musi być odpowiedzią – Potherca

+1

@Potherca: I rzeczywiście,' getopts' to * nie * odpowiedź, jak wyjaśnione zarówno w tym pytaniu, jak iw odpowiedziach na to pytanie. – ruakh

Odpowiedz

14

Zrobiłem coś takiego this:

_setArgs(){ 
    while [ "${1:-}" != "" ]; do 
    case "$1" in 
     "-c" | "--configFile") 
     shift 
     configFile=$1 
     ;; 
     "-f" | "--forceUpdate") 
     forceUpdate=true 
     ;; 
     "-r" | "--forceRetry") 
     forceRetry=true 
     ;; 
    esac 
    shift 
    done 
} 

Jak widać, ten obsługuje zarówno jednorazowego charakteru i dłuższe opcje przyjemnie. Pozwala na powiązanie wartości z każdym argumentem, tak jak w przypadku --configFile. Jest także dość rozciągliwy, bez sztucznych ograniczeń co do tego, jakie opcje można skonfigurować, itp.

Zgodnie z powyższym, "${1:-}" zapobiega błędowi "niezwiązana zmienna" podczas działania w trybie "ścisłym" bash (set -euo pipefail).

+0

To działałoby, ale nie przestrzegałoby niektórych konwencji: składanie pojedynczych liter argumentów i rzeczy takich jak '-configFile = nazwa_pliku' (' = '). –

+1

@IbanBicking - Bardzo prawdziwe. Jednak w moim przypadku postanowiłem pozwolić na to z niezadowoleniem z echa getopt/getops w wielu (choć wciąż wartościowych) odpowiedziach podanych w zaznaczonym duplikacie na http://stackoverflow.com/questions/402377/using-getopts -in-bash-shell-script-to-get-long-and-short-command-line-options. – ziesemer

+0

Ah ... to pytanie nie znalazło się wśród kandydatów na duplikaty, gdy pisałem moje pytanie. Dzięki! –

6

Zakładając, że "chcesz wykonać fantazyjne długie opcje" niezależnie od narzędzia, po prostu idź z getopt (getopts wydaje się być używany głównie, gdy przenośność jest kluczowa). Oto example około maksymalnej złożoności, że dostaniesz:

params="$(getopt -o e:hv -l exclude:,help,verbose --name "$(basename "$0")" -- "[email protected]")" 

if [ $? -ne 0 ] 
then 
    usage 
fi 

eval set -- "$params" 
unset params 

while true 
do 
    case $1 in 
     -e|--exclude) 
      excludes+=("$2") 
      shift 2 
      ;; 
     -h|--help) 
      usage 
      ;; 
     -v|--verbose) 
      verbose='--verbose' 
      shift 
      ;; 
     --) 
      shift 
      break 
      ;; 
     *) 
      usage 
      ;; 
    esac 
done 

Z tego kodu, można określić -e/--exclude więcej niż raz, a ${excludes[@]} będzie zawierać wszystkie podane wyklucza. Po przetworzeniu (-- jest zawsze obecny) wszystko, co pozostało, jest przechowywane w [email protected].

+0

'basename'nie nie przyjmuje ścieżki jako opcji, ale jako argument. (Nie mogłem edytować odpowiedzi, ponieważ system wymaga co najmniej 6 edycji znaków.) – jarno

+0

Dzięki @jarno, nie wiem jak to się włączyło. – l0b0

+1

Inna sprawa, myślę, że nie musisz używać '$ { 2-} ', ale' $ 2' wystarczy, ponieważ 'getopt' zakończy kod niezerowy, jeśli nie ma argumentu dla' -e', prawda? – jarno