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 aangeziengetopts
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 datGETOPT_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.
options
aan het einde noemt niet juist is, zal het-bash: syntax error near unexpected token $@
retourneren. Noem het alsoptions "$@"
.while
voorwaarde mag in plaats daarvan niet(($#))
zijn?$#
? Bewerken: je hebt ' gelijk. Herstel het naarwhile (( "$#" ))