Jak zacházím s přepínači v shell skriptu?

Existují nějaké integrované nástroje, které rozpoznají -x a --xxxx jako přepínače, nikoli jako argumenty, nebo musíte projít všechny vstupní proměnné, otestovat pomlčky a poté analyzovat argumenty?

Odpovědět

Použijte getopts .

Je to celkem přenosný, jak je ve specifikaci POSIX. Bohužel nepodporuje dlouhé možnosti.

Viz také tento getopts výukový program s laskavým svolením wiki bash-hackerů a tato otázka ze stackoverflow.

Pokud potřebujete pouze krátké možnosti, typický vzor použití pro getopts (s použitím tichého hlášení chyb) je:

# process arguments "$1", "$2", ... (i.e. "$@") while getopts "ab:" opt; do case $opt in a) aflag=true ;; # Handle -a b) barg=$OPTARG ;; # Handle -b argument \?) ;; # Handle error: unknown option or missing required argument. esac done 

Komentáře

  • Je třeba zmínit, že getopt by měl být před použitím vždy ověřen jako GNU getopt, ale ' jej stejně nepoužívat protože getopts je stejně přenosnější (a obecně hezčí). Pokud potřebujete to z nějakého důvodu potřebujete zavolat, zavolejte to způsobem specifickým pro GNU, a zajistěte, aby GETOPT_COMPATIBLE nebyl v prostředí.
  • Co dělá dvojtečka v while getopts "ab:" opt?
  • @ user394 : za písmenem možnosti to znamená vyžaduje argument. : jako první znak znamená potlačit chybové zprávy.

odpověď

Předpokládám, že používáte bash nebo podobný program. Příklad:

all=false long=false while getopts ":hal" option; do case $option in h) echo "usage: $0 [-h] [-a] [-l] file ..."; exit ;; a) all=true ;; l) long=true ;; ?) echo "error: option -$OPTARG is not implemented"; exit ;; esac done # remove the options from the positional parameters shift $(( OPTIND - 1 )) ls_opts=() $all && ls_opts+=( -a ) $long && ls_opts+=( -l ) # now, do it ls "${ls_opts[@]}" "$@" 

Komentáře

  • +1 pro použití += s polem. Nevěděl jsi ', že bys to mohl udělat. Hezké!

Odpověď

K analýze parametrů musíte napsat cyklus. Ve skutečnosti můžete použít getopts snadno to uděláte.

Toto je jednoduchý příklad z manuální stránky getopts:

aflag= bflag= while getopts ab: name do case $name in a) aflag=1;; b) bflag=1 bval="$OPTARG";; ?) printf "Usage: %s: [-a] [-b value] args\n" $0 exit 2;; esac done if [ ! -z "$aflag" ]; then printf "Option -a specified\n" fi if [ ! -z "$bflag" ]; then printf "Option -b "%s" specified\n" "$bval" fi shift $(($OPTIND - 1)) printf "Remaining arguments are: %s\n" "$*" 

Odpověď

Nedávno jsem napsal skript pro práci, který byl univerzální a umožňoval více druhů přepínačů v jakémkoli pořadí. zveřejnit celý scénář ze zřejmých právních důvodů (nemluvě o tom, že ho momentálně nemám u sebe), ale tady je jeho maso .. můžete si ho dát i n podprogram a zavolejte jej na konci skriptu:

options () { if [ -n "$1" ]; then # test if any arguments passed - $1 will always exist while (( "$#" )); do # process ALL arguments if [ "$1" = ^-t$ ]; then # -t short for "test" # do something here THEN shift the argument # shift removes it from $@ and reduces $# by # one if you supply no argument shift # we can also process multiple arguments at once elif [[ "$1" =~ ^--test=[:alnum:]{1,8}$ ]] && [[ "$2" =~ ^-t2$ ]] && [[ -n "$3" ]]; then # check for 3 arguments # do something more then remove them ALL from the arg list shift 3 else echo "No matching arguments!" echo "Usage: [script options list here]" fi done else echo "Usage: [script options list here]" exit 0 fi } options "$@" # run options and loop through/process ALL arguments 

Doporučuji omezit váš bash skript na méně než 400 řádků / 15k znaků; můj výše zmíněný skript přesáhl tuto velikost a bylo velmi obtížné na něm pracovat. Začal jsem jej přepisovat v Perlu, což je pro tento úkol mnohem vhodnější. Mějte to na paměti při práci na skriptech v bash. Bash je skvělý pro malé skripty a jednorázové řádky, ale vše složitější a je lepší jej psát v Perlu.

Poznámka, výše uvedené testy netestuji, takže to pravděpodobně nefunguje, ale získáte z toho obecnou představu.

Komentáře

  • Způsob, jakým voláte options na konci není správné, vrátí -bash: syntax error near unexpected token $@. Nazvěte to jako options "$@".
  • Jo, zamíchal jsem Perla a Bash. Opraveno.
  • Tato while podmínka by neměla být místo toho (($#))?
  • Proč potřebujete dvě sady závorek pro $#? Upravit: máte ' pravdu. Opravili jsme to na while (( "$#" ))

Napsat komentář

Vaše e-mailová adresa nebude zveřejněna. Vyžadované informace jsou označeny *