Hoe ga ik om met schakelaars in een shellscript?

Zijn er ingebouwde tools die -x en --xxxx als schakelaars, en geen argumenten, of moet je alle invoervariabelen doorlopen, testen op streepjes en daarna de argumenten parseren?

Antwoord

Gebruik getopts .

Het is redelijk draagbaar zoals het is in de POSIX-specificatie. Helaas ondersteunt het geen lange opties.

Zie ook deze getopts tutorial met dank aan de bash-hackers wiki en deze vraag van stackoverflow.

Als je alleen korte opties nodig hebt, typisch gebruikspatroon voor getopts (met behulp van niet-stille foutrapportage) is:

# 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 

Reacties

  • Er moet worden vermeld dat getopt altijd moet worden geverifieerd als GNU getopt voordat je het gebruikt, maar je moet ' het toch niet gebruiken aangezien getopts draagbaarder is (en over het algemeen prettiger). Als je het toch om de een of andere reden moet noemen, noem het dan op een GNU-specifieke manier, en zorg ervoor dat GETOPT_COMPATIBLE niet in de omgeving staat.
  • Wat doet de dubbele punt in while getopts "ab:" opt?
  • @ user394 De : na een optieletter geeft dit aan vereist een argument. Een : als het eerste teken betekent het onderdrukken van foutmeldingen.

Antwoord

Ik neem aan dat je “bash of iets dergelijks gebruikt. Een voorbeeld:

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[@]}" "$@" 

Reacties

  • +1 voor het gebruik van += met een array. Wist ' niet dat je dat zou kunnen. Leuk!

Answer

Je moet een cyclus schrijven om de parameters te ontleden. Je kunt inderdaad getopts om het gemakkelijk te doen.

Dit is een eenvoudig voorbeeld van de getopts man-pagina:

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" "$*" 

Answer

Ik heb onlangs een script geschreven voor werk dat veelzijdig was en waarin meerdere soorten schakelaars in willekeurige volgorde konden worden gebruikt. openbaar het volledige script om voor de hand liggende juridische redenen (om nog maar te zwijgen van het feit dat ik het momenteel niet bij me heb), maar hier is het vlees ervan .. je kunt het zeggen n een subroutine en noem het aan het einde van je script:

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 

Ik raad je aan om je bash-script te beperken tot minder dan 400 regels / 15k karakters; mijn bovengenoemde script groeide voorbij deze grootte en werd enorm moeilijk om aan te werken. Ik begon het te herschrijven in Perl, wat veel beter geschikt is voor de taak. Houd daar rekening mee terwijl u in bash aan uw scripts werkt. Bash is geweldig voor kleine scripts en oneliners, maar alles wat ingewikkelder is en je “kunt het beter schrijven in Perl.

Opmerking, ik heb het bovenstaande niet getest, dus het werkt waarschijnlijk niet, maar je krijgt er een algemeen idee van.

Reacties

  • De manier waarop je options aan het einde noemt niet juist is, zal het -bash: syntax error near unexpected token $@ retourneren. Noem het als options "$@".
  • Ja, ik heb Perl en Bash. Gecorrigeerd.
  • Die while voorwaarde mag in plaats daarvan niet (($#)) zijn?
  • Waarom heb je twee paar haakjes nodig voor $#? Bewerken: je hebt ' gelijk. Herstel het naar while (( "$#" ))

Geef een reactie

Het e-mailadres wordt niet gepubliceerd. Vereiste velden zijn gemarkeerd met *