Frage

Ich wünsche lange und kurze Formen der Kommandozeilenoptionen haben aufgerufen mein Shell-Skript verwendet wird.

Ich weiß, dass getopts verwendet werden kann, aber wie in Perl, ich habe nicht in der Lage gewesen, mit Schale, das gleiche zu tun.

Alle Ideen, wie dies getan werden kann, so dass ich Optionen wie verwenden kann:

./shell.sh --copyfile abc.pl /tmp/
./shell.sh -c abc.pl /tmp/

In dem obigen sowohl die Befehle, die gleiche Sache zu meiner Schale bedeuten, aber mit getopts, habe ich nicht in der Lage gewesen, diese zu implementieren?

War es hilfreich?

Lösung

Es gibt drei Implementierungen, die in Betracht gezogen werden:

  • Bash builtin getopts. Dies unterstützt nicht lange Optionsnamen mit dem Doppel-Bindestrich-Präfix. Es unterstützt nur Einzelzeichenoptionen.

  • BSD UNIX-Implementierung von eigenständigem getopt Kommando (das ist, was MacOS verwendet). Dies gilt auch nicht lange Optionen unterstützen.

  • GNU-Implementierung von eigenständigen getopt. GNU getopt(3) (durch die verwendete Befehlszeilen getopt(1) auf Linux) unterstützt lange Optionen Parsen.


Einige andere Antworten zeigen eine Lösung für den Bash-Builtin getopts mit langen Optionen zu imitieren. Diese Lösung macht eigentlich eine kurze Option deren Charakter „-“. So erhalten Sie „-“ als die Fahne. Dann nichts folgt, wird OPTARG, und testen Sie die OPTARG mit einer verschachtelten case.

Das ist klug, aber es kommt mit Einschränkungen:

  • getopts kann die Opt-Spezifikation nicht erzwingen. Es kann keine Fehler zurück, wenn der Benutzer eine ungültige Option liefert. Sie haben eine eigene Fehlerprüfung zu tun, wie Sie OPTARG analysieren.
  • OPTARG wird für die langen Optionsnamen verwendet, die Nutzung erschwert, wenn die lange Option selbst ein Argument hat. Am Ende haben Sie, dass Sie sich als zusätzlichen Fall codieren zu müssen.

So, während es möglich ist, mehr Code zu schreiben, um den Mangel an Unterstützung für lange Optionen zu arbeiten, das viel mehr Arbeit ist und besiegt teilweise den Zweck, einen getopt Parser verwenden Sie den Code zu vereinfachen.

Andere Tipps

getopt und getopts sind verschiedene Tiere und Menschen scheinen ein wenig Missverständnis zu haben, was sie tun. getopts ist eine integrierte Kommando bash Befehlszeilenoptionen in einer Schleife zu verarbeiten und zu jeder gefundene Option und Wert wiederum zu integrierten Variablen zuweisen, so dass Sie sie weiter verarbeiten können. getopt ist jedoch ein externes Hilfsprogramm, und es nicht wirklich Ihre Möglichkeiten für Sie verarbeitet , um die Art und Weise, zum Beispiel bash getopts, der Perl Getopt Modul oder der Python optparse / argparse Module tun. Alles, was getopt tut, ist die Optionen canonicalize, die übergeben werden - das heißt wandeln sie in eine Standard-Form, so dass es einfacher für ein Shell-Skript, um sie zu verarbeiten. Zum Beispiel könnte eine Anwendung von getopt wandeln die folgenden:

myscript -ab infile.txt -ooutfile.txt

in diesen:

myscript -a -b -o outfile.txt infile.txt

Sie haben die tatsächliche tun sich verarbeiten. Sie müssen nicht getopt verwenden überhaupt, wenn Sie verschiedene Beschränkungen für die Art und Weise machen Sie Optionen angeben:

  • setzen nur eine Option pro Argument;
  • gehen alle Optionen, bevor irgendwelche Positionsparameter (d Nicht-Option Argumente);
  • für Optionen mit Werten (z -o oben), der Wert hat als separates Argument gehen (nach einem Leerzeichen).

Warum Verwendung getopt statt getopts? Der Hauptgrund ist, dass nur GNU getopt gibt Sie lange genannten Befehlszeilenoptionen unterstützen für. 1 (GNU getopt ist die Standardeinstellung auf Linux. Mac OS X und FreeBSD ist mit einem grundlegenden und nicht sehr -Nützlich getopt, aber die GNU-Version installiert werden kann, s. unten)

Zum Beispiel, hier ist ein Beispiel für die Verwendung GNU getopt, aus einem Skript von mir genannt javawrap:

# NOTE: This requires GNU getopt.  On Mac OS X and FreeBSD, you have to install this
# separately; see below.
TEMP=`getopt -o vdm: --long verbose,debug,memory:,debugfile:,minheap:,maxheap: \
             -n 'javawrap' -- "$@"`

if [ $? != 0 ] ; then echo "Terminating..." >&2 ; exit 1 ; fi

# Note the quotes around `$TEMP': they are essential!
eval set -- "$TEMP"

VERBOSE=false
DEBUG=false
MEMORY=
DEBUGFILE=
JAVA_MISC_OPT=
while true; do
  case "$1" in
    -v | --verbose ) VERBOSE=true; shift ;;
    -d | --debug ) DEBUG=true; shift ;;
    -m | --memory ) MEMORY="$2"; shift 2 ;;
    --debugfile ) DEBUGFILE="$2"; shift 2 ;;
    --minheap )
      JAVA_MISC_OPT="$JAVA_MISC_OPT -XX:MinHeapFreeRatio=$2"; shift 2 ;;
    --maxheap )
      JAVA_MISC_OPT="$JAVA_MISC_OPT -XX:MaxHeapFreeRatio=$2"; shift 2 ;;
    -- ) shift; break ;;
    * ) break ;;
  esac
done

Auf diese Weise können Sie Optionen wie --verbose -dm4096 --minh=20 --maxhe 40 --debugfi="/Users/John Johnson/debug.txt" oder ähnliches angeben. Die Wirkung des Aufrufs getopt ist es, die Optionen zu --verbose -d -m 4096 --minheap 20 --maxheap 40 --debugfile "/Users/John Johnson/debug.txt" normalisieren, so dass Sie leichter sie verarbeiten können. Die zitierte um "$1" und "$2" ist wichtig, da sie, dass in ihnen Argumente mit Leerzeichen sorgt für richtig gehandhabt erhalten.

Wenn Sie die ersten 9 Zeilen (alles nach oben durch die eval set Linie) löschen, wird der Code arbeitet immer noch ! Allerdings wird der Code viel wählerische, in welcher Art von Optionen es akzeptiert: Insbesondere werden Sie alle Optionen in der „kanonischen“ oben beschriebenen Form angeben. Mit dem Einsatz von getopt, jedoch können Sie Gruppe aus einem Buchstaben Optionen verwenden kürzere nicht-mehrdeutige Formen der Lang Optionen, entweder den --file foo.txt oder --file=foo.txt Stil, verwenden Sie entweder den -m 4096 oder -m4096 Stil, mischten Optionen und Nicht-Optionen in jede Bestellung, usw. getopt auch eine Fehlermeldung aus, wenn nicht erkannt oder mehrdeutig Optionen zu finden sind.

Hinweis : Es gibt eigentlich zwei ganz anders Versionen von getopt, Grunde getopt und GNU getopt, mit unterschiedlichen Funktionen und verschiedenen Aufrufkonventionen 2 Grund getopt ganz gebrochen ist: nicht nur, dass es lange Optionen nicht verarbeiten, auch kann es nicht einmal innerhalb von Argumenten oder leerer Argumenten eingebettete Leerzeichen verarbeiten, während getopts dieses Recht nicht tun. Der obige Code wird nicht in Grund getopt arbeiten. GNU getopt ist standardmäßig auf Linux installiert, aber unter Mac OS X und FreeBSD muss separat installiert werden. Unter Mac OS X installieren MacPorts ( http://www.macports.org ) und führen Sie dann sudo port install getopt GNU getopt zu installieren (in der Regel in /opt/local/bin ), und stellen Sie sicher, dass /opt/local/bin in der Shell Weg vor /usr/bin ist. Unter FreeBSDInstallieren Sie misc/getopt.

Eine Kurzanleitung des Beispielcode für Ihr eigenes Programm zu ändern: Von den ersten Zeilen, das ist alles „vorformulierten“, das gleich bleiben sollte, mit Ausnahme der Linie, die getopt aufruft. Sie sollten die Programmnamen nach -n ändern, kurzen Optionen nach -o und langen Optionen nach --long angeben. Setzen Sie einen Doppelpunkt nach Optionen, die einen Wert annehmen.

Schließlich, wenn Sie Code zu sehen, dass anstelle von set nur eval set hat, wurde es für BSD getopt geschrieben. Sie sollten es ändern, um den eval set Stil zu verwenden, die mit beiden Versionen von getopt funktioniert gut, während die Ebene set nicht direkt mit GNU getopt funktioniert.

1 Eigentlich getopts in ksh93 unterstützt lange genannten Optionen, aber diese Schale ist nicht so oft wie bash verwendet. In zsh verwenden zparseopts diese Funktionalität zu erhalten.

2 Technisch "GNU getopt" eine falsche Bezeichnung ist; Diese Version wurde eigentlich für Linux geschrieben, anstatt das GNU-Projekt. Jedoch ergibt sich alle GNU-Konventionen, und der Begriff „GNU getopt“ wird häufig verwendet (zum Beispiel auf FreeBSD).

Die Bash gebautet getopts Funktion kann durch einen Doppelpunkt in die optspec gefolgt lange Optionen verwendet werden, um zu analysieren, indem ein Strichzeichen setzen:

#!/usr/bin/env bash 
optspec=":hv-:"
while getopts "$optspec" optchar; do
    case "${optchar}" in
        -)
            case "${OPTARG}" in
                loglevel)
                    val="${!OPTIND}"; OPTIND=$(( $OPTIND + 1 ))
                    echo "Parsing option: '--${OPTARG}', value: '${val}'" >&2;
                    ;;
                loglevel=*)
                    val=${OPTARG#*=}
                    opt=${OPTARG%=$val}
                    echo "Parsing option: '--${opt}', value: '${val}'" >&2
                    ;;
                *)
                    if [ "$OPTERR" = 1 ] && [ "${optspec:0:1}" != ":" ]; then
                        echo "Unknown option --${OPTARG}" >&2
                    fi
                    ;;
            esac;;
        h)
            echo "usage: $0 [-v] [--loglevel[=]<value>]" >&2
            exit 2
            ;;
        v)
            echo "Parsing option: '-${optchar}'" >&2
            ;;
        *)
            if [ "$OPTERR" != 1 ] || [ "${optspec:0:1}" = ":" ]; then
                echo "Non-option argument: '-${OPTARG}'" >&2
            fi
            ;;
    esac
done

Nach dem Kopieren auf ausführbare Datei name = getopts_test.sh im aktuellen Arbeitsverzeichnis , kann ein Ausgangssignal erzeugen wie

$ ./getopts_test.sh
$ ./getopts_test.sh -f
Non-option argument: '-f'
$ ./getopts_test.sh -h
usage: code/getopts_test.sh [-v] [--loglevel[=]<value>]
$ ./getopts_test.sh --help
$ ./getopts_test.sh -v
Parsing option: '-v'
$ ./getopts_test.sh --very-bad
$ ./getopts_test.sh --loglevel
Parsing option: '--loglevel', value: ''
$ ./getopts_test.sh --loglevel 11
Parsing option: '--loglevel', value: '11'
$ ./getopts_test.sh --loglevel=11
Parsing option: '--loglevel', value: '11'

Offensichtlich getopts weder führt OPTERR Prüfung noch Option-Argument für die langen Optionen Parsen. Das Skript, das oben zeigt, wie dies manuell durchgeführt werden kann. Das Grundprinzip funktioniert auch in der Debian Almquist Shell ( „Strich“). Beachten Sie den Sonderfall:

getopts -- "-:"  ## without the option terminator "-- " bash complains about "-:"
getopts "-:"     ## this works in the Debian Almquist shell ("dash")

Beachten Sie, dass, wie GreyCat von über unter http://mywiki.wooledge.org/BashFAQ Punkte out, nutzt dieser Trick ein nicht standardmäßiges Verhalten der Schale, die das Option-Argument (dh in dem Dateinamen „-f Dateinamen“) erlaubt (wie in „-fDateiname“) an die Option konkateniert werden. Die POSIX Standard sagt, es muss ein Raum zwischen ihnen sein, die in den Fall von "- longoption". würde die Option-Parsing beenden und alle longoptions in nicht-Option Argumente drehen

Der eingebaute in getopts Befehl noch, AFAIK, beschränkt auf Einzelzeichen Optionen nur.

Es gibt (oder früher) ein externes Programm getopt, die eine Reihe von Optionen, so dass es leichter war, zu analysieren reorganisieren würden. Sie könnten, dass Design anpassen lange Optionen zu behandeln. Beispiel für die Verwendung:

aflag=no
bflag=no
flist=""
set -- $(getopt abf: "$@")
while [ $# -gt 0 ]
do
    case "$1" in
    (-a) aflag=yes;;
    (-b) bflag=yes;;
    (-f) flist="$flist $2"; shift;;
    (--) shift; break;;
    (-*) echo "$0: error - unrecognized option $1" 1>&2; exit 1;;
    (*)  break;;
    esac
    shift
done

# Process remaining non-option arguments
...

Sie ein ähnliches Schema mit einem getoptlong Befehl verwenden können.

Hinweis

, dass die fundamentale Schwäche mit dem externen getopt Programm ist die Schwierigkeit der Argumente mit Leerzeichen in Umgang mit ihnen, und in diesen Räume genau zu erhalten. Aus diesem Grunde ist das eingebaute in getopts überlegen ist, wenn auch durch die Tatsache, es Ein-Buchstaben-Optionen nur behandelt.

Hier ist ein Beispiel, das tatsächlich verwendet getopt mit langen Optionen:

aflag=no
bflag=no
cargument=none

# options may be followed by one colon to indicate they have a required argument
if ! options=$(getopt -o abc: -l along,blong,clong: -- "$@")
then
    # something went wrong, getopt will put out an error message for us
    exit 1
fi

set -- $options

while [ $# -gt 0 ]
do
    case $1 in
    -a|--along) aflag="yes" ;;
    -b|--blong) bflag="yes" ;;
    # for options with required arguments, an additional shift is required
    -c|--clong) cargument="$2" ; shift;;
    (--) shift; break;;
    (-*) echo "$0: error - unrecognized option $1" 1>&2; exit 1;;
    (*) break;;
    esac
    shift
done

Lange Optionen können durch den Standard getopts gebautet als „Argument“ die - „Option“

analysiert werden

Dies ist tragbar und nativen POSIX-Shell - keine externen Programme oder bashisms benötigt werden,

.

Dieses Handbuch implementiert lange Optionen als Argumente für die - Option, so --alpha durch getopts als - mit dem Argument alpha und --bravo=foo als - mit dem Argument bravo=foo gesehen. Das wahre Argument kann mit einem einfachen Ersatz geerntet wird. ${OPTARG#*=}

In diesem Beispiel -b (und seine lange Form, --bravo) hat eine verbindliche Option (beachten Sie die manuelle Rekonstruktion, dass für die lange Form der Durchsetzung). Nicht-Booleschen Optionen lange Argumente kommen nach Gleichheitszeichen, z.B. --bravo=foo (Raumtrennzeichen für lange Optionen zu implementieren wäre schwer).

Da diese getopts verwendet, unterstützt diese Lösung Nutzung wie cmd -ac --bravo=foo -d FILE (die Optionen -a und -c kombiniert hat und verschachtelt lange Optionen mit Standardoptionen), während die meisten anderen Antworten hier entweder Kampf oder nicht, das zu tun.

while getopts ab:c-: arg; do
  case $arg in
    a )  ARG_A=true ;;
    b )  ARG_B="$OPTARG" ;;
    c )  ARG_C=true ;;
    - )  LONG_OPTARG="${OPTARG#*=}"
         case $OPTARG in
           alpha    )  ARG_A=true ;;
           bravo=?* )  ARG_B="$LONG_OPTARG" ;;
           bravo*   )  echo "No arg for --$OPTARG option" >&2; exit 2 ;;
           charlie  )  ARG_C=true ;;
           alpha* | charlie* )
                       echo "No arg allowed for --$OPTARG option" >&2; exit 2 ;;
           '' )        break ;; # "--" terminates argument processing
           * )         echo "Illegal option --$OPTARG" >&2; exit 2 ;;
         esac ;;
    \? ) exit 2 ;;  # getopts already reported the illegal option
  esac
done
shift $((OPTIND-1)) # remove parsed options and args from $@ list

Wenn das Argument ein Bindestrich (-), hat es zwei weitere Komponenten: der Flag-Namen und (optional) ihr Argument. Ich begrenzen diese den Standardweg jeden Befehl würde mit dem ersten Gleichheitszeichen (=). $LONG_OPTARG ist daher lediglich der Inhalt von $OPTARG ohne den Flag-Namen oder Gleichheitszeichen.

Die innere case implementiert lange Optionen manuell, so braucht es einige Housekeeping:

  • bravo=? Spiele --bravo=foo aber nicht --bravo= (Anmerkung: case stoppt nach dem ersten Spiel)
  • bravo* folgt, unter Hinweis auf die fehlende erforderliche Argument in --bravo und --bravo=
  • alpha* | charlie* Argumente fängt die Optionen gegeben, die sie nicht unterstützen
  • '' vorhanden ist, nicht-Optionen zu unterstützen, die mit Bindestrichen starten passieren
  • * fängt alle anderen lange Optionen und erstellt den Fehler durch getopts für eine ungültige Option geworfen

Sie müssen nicht unbedingt alle diese Housekeeping Angaben müssen. Zum Beispiel, vielleicht wollen Sie --bravo ein haben, optional Argument (die -b nicht aufgrund einer Einschränkung in getopts unterstützen kann). Lediglich entfernen Sie die =? und den damit verbundenen Fehlerfall und rufen Sie dann ${ARG_B:=$DEFAULT_ARG_B} Sie das erste Mal $ARG_B verwenden.


lange Optionen mit Leerzeichen getrennte Argumente zu übernehmen, müssen Sie eine (anständig safe) eval:

           bravo=?* )  ARG_B="$LONG_OPTARG" ;;
           bravo )     eval "ARG_B=\"\$$OPTIND\""
                       if [ -z "$ARG_B" ]; then
                         echo "No arg for --$OPTARG option" >&2; exit 2
                       fi
                       OPTIND=$((OPTIND+1)) ;;
           bravo*   )  echo "No arg for --$OPTARG option" >&2; exit 2 ;;

Diese zusätzliche Klausel hinzugefügt direkt nach der = Zuordnung Version läuft ein eval den Wert des Parameters nach der Option interpretieren zu der Zeit interpretiert. Bash kann diese mehr tun, sauber mit indirekter Erweiterung , ARG_B="${!OPTIND}" und Zsh kann es mit dem Parameter Expansion P Flagge , ARGB="${(P)OPTIND}", aber die eval benötigt wird vollständig portable POSIX sein. $OPTIND eine Zahl auf die nächste Shell-Argument bezieht, sagen $2 (was bedeutet, $1 ist --bravo). Die eval wäre dann ARG_B="$2" zu interpretieren und weil dieser in Anführungszeichen eingeschlossen ist, ist es sicher vor Missbrauch (ich kann nicht einen Weg finden, es dazu zu verleiten, etwas Unpassendes zu tun).

Die Gewährleistung ein nicht-leerer Wert ist nicht trivial und erfordert tatsächlich überprüft, so haben wir eine bedingte und erzeugen einen fatalen Fehler in thim Fall. Wenn Sie es erlauben, leer zu sein, müssen Sie das Inkrementieren von $OPTIND konditionalisieren oder auch in eine Endlosschleife laufen. [ $# -gt $OPTIND ] && OPTIND=$((OPTIND+1)) tun sollte.

Der letzte Teil dieser Addition Klausel erhöht $OPTIND richtig die Option Argument aufnehmen und zur nächsten Option wechseln.

Werfen Sie einen Blick auf shFlags , die eine tragbare Shell-Bibliothek ist (was bedeutet, :.. sh, bash, Bindestrich, kSH, zsh unter Linux, Solaris, etc.)

Es macht neue Fahnen Hinzufügen so einfach wie eine Zeile zu Ihrem Skript hinzufügen, und es gibt eine automatisch generierten Nutzungsfunktion.

Hier ist ein einfaches Hello, world! mit shflag gültigen :

#!/bin/sh

# source shflags from current directory
. ./shflags

# define a 'name' command-line string flag
DEFINE_string 'name' 'world' 'name to say hello to' 'n'

# parse the command-line
FLAGS "$@" || exit 1
eval set -- "${FLAGS_ARGV}"

# say hello
echo "Hello, ${FLAGS_name}!"

Für OSes, die die verbesserte getopt haben, die lange Optionen (zum Beispiel Linux) unterstützt, können Sie tun:

$ ./hello_world.sh --name Kate
Hello, Kate!

Für den Rest müssen Sie die Short-Option verwenden:

$ ./hello_world.sh -n Kate
Hello, Kate!

ein neues Flag hinzuzufügen ist so einfach wie eine neue DEFINE_ call hinzugefügt wird.

Mit getopts mit kurzen / langen Optionen und Argumenten


Funktioniert mit allen Kombinationen, z:

  • foobar -f --bar
  • foobar --foo -b
  • foobar -BF --bar --foobar
  • foobar -fbFBAshorty --bar -FB --arguments = Longhorn
  • foobar -fA "text shorty" -B --arguments = "text Longhorn"
  • bash foobar -F --barfoo
  • sh foobar -B --foobar - ...
  • bash ./foobar -F --bar

Einige Erklärungen für dieses Beispiel

Options=$@
Optnum=$#
sfoo='no '
sbar='no '
sfoobar='no '
sbarfoo='no '
sarguments='no '
sARG=empty
lfoo='no '
lbar='no '
lfoobar='no '
lbarfoo='no '
larguments='no '
lARG=empty

Wie die Nutzungsfunktion aussieht

würde
function _usage() 
{
  ###### U S A G E : Help and ERROR ######
  cat <<EOF
   foobar $Options
  $*
          Usage: foobar <[options]>
          Options:
                  -b   --bar            Set bar to yes    ($foo)
                  -f   --foo            Set foo to yes    ($bart)
                  -h   --help           Show this message
                  -A   --arguments=...  Set arguments to yes ($arguments) AND get ARGUMENT ($ARG)
                  -B   --barfoo         Set barfoo to yes ($barfoo)
                  -F   --foobar         Set foobar to yes ($foobar)
EOF
}

[ $# = 0 ] && _usage "  >>>>>>>> no options given "

getops mit Long- / Short-Fahnen sowie lange Argumente

while getopts ':bfh-A:BF' OPTION ; do
  case "$OPTION" in
    b  ) sbar=yes                       ;;
    f  ) sfoo=yes                       ;;
    h  ) _usage                         ;;   
    A  ) sarguments=yes;sARG="$OPTARG"  ;;
    B  ) sbarfoo=yes                    ;;
    F  ) sfoobar=yes                    ;;
    -  ) [ $OPTIND -ge 1 ] && optind=$(expr $OPTIND - 1 ) || optind=$OPTIND
         eval OPTION="\$$optind"
         OPTARG=$(echo $OPTION | cut -d'=' -f2)
         OPTION=$(echo $OPTION | cut -d'=' -f1)
         case $OPTION in
             --foo       ) lfoo=yes                       ;;
             --bar       ) lbar=yes                       ;;
             --foobar    ) lfoobar=yes                    ;;
             --barfoo    ) lbarfoo=yes                    ;;
             --help      ) _usage                         ;;
             --arguments ) larguments=yes;lARG="$OPTARG"  ;; 
             * )  _usage " Long: >>>>>>>> invalid options (long) " ;;
         esac
       OPTIND=1
       shift
      ;;
    ? )  _usage "Short: >>>>>>>> invalid options (short) "  ;;
  esac
done

Ausgabe

##################################################################
echo "----------------------------------------------------------"
echo "RESULT short-foo      : $sfoo                                    long-foo      : $lfoo"
echo "RESULT short-bar      : $sbar                                    long-bar      : $lbar"
echo "RESULT short-foobar   : $sfoobar                                 long-foobar   : $lfoobar"
echo "RESULT short-barfoo   : $sbarfoo                                 long-barfoo   : $lbarfoo"
echo "RESULT short-arguments: $sarguments  with Argument = \"$sARG\"   long-arguments: $larguments and $lARG"

die oben in eine zusammenhängende Skript Kombination

#!/bin/bash
# foobar: getopts with short and long options AND arguments

function _cleanup ()
{
  unset -f _usage _cleanup ; return 0
}

## Clear out nested functions on exit
trap _cleanup INT EXIT RETURN

###### some declarations for this example ######
Options=$@
Optnum=$#
sfoo='no '
sbar='no '
sfoobar='no '
sbarfoo='no '
sarguments='no '
sARG=empty
lfoo='no '
lbar='no '
lfoobar='no '
lbarfoo='no '
larguments='no '
lARG=empty

function _usage() 
{
  ###### U S A G E : Help and ERROR ######
  cat <<EOF
   foobar $Options
   $*
          Usage: foobar <[options]>
          Options:
                  -b   --bar            Set bar to yes    ($foo)
                    -f   --foo            Set foo to yes    ($bart)
                      -h   --help           Show this message
                  -A   --arguments=...  Set arguments to yes ($arguments) AND get ARGUMENT ($ARG)
                  -B   --barfoo         Set barfoo to yes ($barfoo)
                  -F   --foobar         Set foobar to yes ($foobar)
EOF
}

[ $# = 0 ] && _usage "  >>>>>>>> no options given "

##################################################################    
#######  "getopts" with: short options  AND  long options  #######
#######            AND  short/long arguments               #######
while getopts ':bfh-A:BF' OPTION ; do
  case "$OPTION" in
    b  ) sbar=yes                       ;;
    f  ) sfoo=yes                       ;;
    h  ) _usage                         ;;   
    A  ) sarguments=yes;sARG="$OPTARG"  ;;
    B  ) sbarfoo=yes                    ;;
    F  ) sfoobar=yes                    ;;
    -  ) [ $OPTIND -ge 1 ] && optind=$(expr $OPTIND - 1 ) || optind=$OPTIND
         eval OPTION="\$$optind"
         OPTARG=$(echo $OPTION | cut -d'=' -f2)
         OPTION=$(echo $OPTION | cut -d'=' -f1)
         case $OPTION in
             --foo       ) lfoo=yes                       ;;
             --bar       ) lbar=yes                       ;;
             --foobar    ) lfoobar=yes                    ;;
             --barfoo    ) lbarfoo=yes                    ;;
             --help      ) _usage                         ;;
               --arguments ) larguments=yes;lARG="$OPTARG"  ;; 
             * )  _usage " Long: >>>>>>>> invalid options (long) " ;;
         esac
       OPTIND=1
       shift
      ;;
    ? )  _usage "Short: >>>>>>>> invalid options (short) "  ;;
  esac
done

Eine andere Art und Weise ...

# translate long options to short
for arg
do
    delim=""
    case "$arg" in
       --help) args="${args}-h ";;
       --verbose) args="${args}-v ";;
       --config) args="${args}-c ";;
       # pass through anything else
       *) [[ "${arg:0:1}" == "-" ]] || delim="\""
           args="${args}${delim}${arg}${delim} ";;
    esac
done
# reset the translated args
eval set -- $args
# now we can process with getopt
while getopts ":hvc:" opt; do
    case $opt in
        h)  usage ;;
        v)  VERBOSE=true ;;
        c)  source $OPTARG ;;
        \?) usage ;;
        :)
        echo "option -$OPTARG requires an argument"
        usage
        ;;
    esac
done

Ich löste Art auf diese Weise:

# A string with command options
options=$@

# An array with all the arguments
arguments=($options)

# Loop index
index=0

for argument in $options
  do
    # Incrementing index
    index=`expr $index + 1`

    # The conditions
    case $argument in
      -a) echo "key $argument value ${arguments[index]}" ;;
      -abc) echo "key $argument value ${arguments[index]}" ;;
    esac
  done

exit;

Bin ich dumm oder etwas zu sein? getopt und getopts sind so verwirrend.

Falls Sie nicht die getopt Abhängigkeit möchten, können Sie dies tun:

while test $# -gt 0
do
  case $1 in

  # Normal option processing
    -h | --help)
      # usage and help
      ;;
    -v | --version)
      # version info
      ;;
  # ...

  # Special cases
    --)
      break
      ;;
    --*)
      # error unknown (long) option $1
      ;;
    -?)
      # error unknown (short) option $1
      ;;

  # FUN STUFF HERE:
  # Split apart combined short options
    -*)
      split=$1
      shift
      set -- $(echo "$split" | cut -c 2- | sed 's/./-& /g') "$@"
      continue
      ;;

  # Done with options
    *)
      break
      ;;
  esac

  # for testing purposes:
  echo "$1"

  shift
done

Natürlich, dann kann man nicht lange Stil-Optionen mit einem Bindestrich. Und wenn Sie verkürzte Versionen hinzufügen möchten (z --verbos statt --verbose), dann müssen Sie diese manuell hinzufügen.

Aber wenn Sie schauen, getopts Funktionalität zusammen mit langen Optionen zu erhalten, ist dies eine einfache Möglichkeit, es zu tun.

Ich habe auch diese Schnipsel in einem Kern .

Das eingebaute in getopts kann dies nicht tun. Es gibt eine externe getopt (1) Programm, das dies tun können, aber man es nur auf Linux erhalten aus dem util-linux Paket. Es kommt mit einem Beispielskript getopt-parse.bash .

Es gibt auch eine getopts_long als Shell-Funktion geschrieben.

#!/bin/bash
while getopts "abc:d:" flag
do
  case $flag in
    a) echo "[getopts:$OPTIND]==> -$flag";;
    b) echo "[getopts:$OPTIND]==> -$flag";;
    c) echo "[getopts:$OPTIND]==> -$flag $OPTARG";;
    d) echo "[getopts:$OPTIND]==> -$flag $OPTARG";;
  esac
done

shift $((OPTIND-1))
echo "[otheropts]==> $@"

exit

.

#!/bin/bash
until [ -z "$1" ]; do
  case $1 in
    "--dlong")
      shift
      if [ "${1:1:0}" != "-" ]
      then
        echo "==> dlong $1"
        shift
      fi;;
    *) echo "==> other $1"; shift;;
  esac
done
exit

In ksh93, tut getopts lange Namen unterstützen ...

while getopts "f(file):s(server):" flag
do
    echo "$flag" $OPTIND $OPTARG
done

Oder so die Tutorials, die ich gefunden habe gesagt haben. Probieren Sie es aus und sehen.

Inventing noch eine weitere Version des Rades ...

Diese Funktion ist ein (hoffentlich) POSIX-kompatibel für GNU Getopt Klar Bourne-Shell-Ersatz. Es unterstützt lange / kurze Optionen, die zwingend / optional / keine Argumente annehmen können, und die Art und Weise, in den Optionen angegeben sind fast identisch mit GNU getopt ist, so Konvertierung ist trivial.

Natürlich ist dies immer noch ein beträchtlicher Teil des Codes in ein Skript zu löschen, aber es ist etwa die Hälfte der Zeilen der bekannten getopt_long Shell-Funktion und kann in Fällen vorzuziehen sein, wo Sie wollen nur bestehendes GNU getopt Anwendungen ersetzen .

Das ist ziemlich neuer Code, so YMMV (und auf jeden Fall lassen Sie es mich wissen, wenn dies aus irgendeinem Grunde nicht wirklich POSIX-kompatibel ist - Portabilität die Absicht von Anfang an war, aber ich habe keinen nützlichen POSIX Test hat Umwelt).

-Code und Beispiel-Anwendung folgt:

#!/bin/sh
# posix_getopt shell function
# Author: Phil S.
# Version: 1.0
# Created: 2016-07-05
# URL: http://stackoverflow.com/a/37087374/324105

# POSIX-compatible argument quoting and parameter save/restore
# http://www.etalabs.net/sh_tricks.html
# Usage:
# parameters=$(save "$@") # save the original parameters.
# eval "set -- ${parameters}" # restore the saved parameters.
save () {
    local param
    for param; do
        printf %s\\n "$param" \
            | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/"
    done
    printf %s\\n " "
}

# Exit with status $1 after displaying error message $2.
exiterr () {
    printf %s\\n "$2" >&2
    exit $1
}

# POSIX-compatible command line option parsing.
# This function supports long options and optional arguments, and is
# a (largely-compatible) drop-in replacement for GNU getopt.
#
# Instead of:
# opts=$(getopt -o "$shortopts" -l "$longopts" -- "$@")
# eval set -- ${opts}
#
# We instead use:
# opts=$(posix_getopt "$shortopts" "$longopts" "$@")
# eval "set -- ${opts}"
posix_getopt () { # args: "$shortopts" "$longopts" "$@"
    local shortopts longopts \
          arg argtype getopt nonopt opt optchar optword suffix

    shortopts="$1"
    longopts="$2"
    shift 2

    getopt=
    nonopt=
    while [ $# -gt 0 ]; do
        opt=
        arg=
        argtype=
        case "$1" in
            # '--' means don't parse the remaining options
            ( -- ) {
                getopt="${getopt}$(save "$@")"
                shift $#
                break
            };;
            # process short option
            ( -[!-]* ) {         # -x[foo]
                suffix=${1#-?}   # foo
                opt=${1%$suffix} # -x
                optchar=${opt#-} # x
                case "${shortopts}" in
                    ( *${optchar}::* ) { # optional argument
                        argtype=optional
                        arg="${suffix}"
                        shift
                    };;
                    ( *${optchar}:* ) { # required argument
                        argtype=required
                        if [ -n "${suffix}" ]; then
                            arg="${suffix}"
                            shift
                        else
                            case "$2" in
                                ( -* ) exiterr 1 "$1 requires an argument";;
                                ( ?* ) arg="$2"; shift 2;;
                                (  * ) exiterr 1 "$1 requires an argument";;
                            esac
                        fi
                    };;
                    ( *${optchar}* ) { # no argument
                        argtype=none
                        arg=
                        shift
                        # Handle multiple no-argument parameters combined as
                        # -xyz instead of -x -y -z. If we have just shifted
                        # parameter -xyz, we now replace it with -yz (which
                        # will be processed in the next iteration).
                        if [ -n "${suffix}" ]; then
                            eval "set -- $(save "-${suffix}")$(save "$@")"
                        fi
                    };;
                    ( * ) exiterr 1 "Unknown option $1";;
                esac
            };;
            # process long option
            ( --?* ) {            # --xarg[=foo]
                suffix=${1#*=}    # foo (unless there was no =)
                if [ "${suffix}" = "$1" ]; then
                    suffix=
                fi
                opt=${1%=$suffix} # --xarg
                optword=${opt#--} # xarg
                case ",${longopts}," in
                    ( *,${optword}::,* ) { # optional argument
                        argtype=optional
                        arg="${suffix}"
                        shift
                    };;
                    ( *,${optword}:,* ) { # required argument
                        argtype=required
                        if [ -n "${suffix}" ]; then
                            arg="${suffix}"
                            shift
                        else
                            case "$2" in
                                ( -* ) exiterr 1 \
                                       "--${optword} requires an argument";;
                                ( ?* ) arg="$2"; shift 2;;
                                (  * ) exiterr 1 \
                                       "--${optword} requires an argument";;
                            esac
                        fi
                    };;
                    ( *,${optword},* ) { # no argument
                        if [ -n "${suffix}" ]; then
                            exiterr 1 "--${optword} does not take an argument"
                        fi
                        argtype=none
                        arg=
                        shift
                    };;
                    ( * ) exiterr 1 "Unknown option $1";;
                esac
            };;
            # any other parameters starting with -
            ( -* ) exiterr 1 "Unknown option $1";;
            # remember non-option parameters
            ( * ) nonopt="${nonopt}$(save "$1")"; shift;;
        esac

        if [ -n "${opt}" ]; then
            getopt="${getopt}$(save "$opt")"
            case "${argtype}" in
                ( optional|required ) {
                    getopt="${getopt}$(save "$arg")"
                };;
            esac
        fi
    done

    # Generate function output, suitable for:
    # eval "set -- $(posix_getopt ...)"
    printf %s "${getopt}"
    if [ -n "${nonopt}" ]; then
        printf %s "$(save "--")${nonopt}"
    fi
}

Beispiel Nutzung:

# Process command line options
shortopts="hvd:c::s::L:D"
longopts="help,version,directory:,client::,server::,load:,delete"
#opts=$(getopt -o "$shortopts" -l "$longopts" -n "$(basename $0)" -- "$@")
opts=$(posix_getopt "$shortopts" "$longopts" "$@")
if [ $? -eq 0 ]; then
    #eval set -- ${opts}
    eval "set -- ${opts}"
    while [ $# -gt 0 ]; do
        case "$1" in
            ( --                ) shift; break;;
            ( -h|--help         ) help=1; shift; break;;
            ( -v|--version      ) version_help=1; shift; break;;
            ( -d|--directory    ) dir=$2; shift 2;;
            ( -c|--client       ) useclient=1; client=$2; shift 2;;
            ( -s|--server       ) startserver=1; server_name=$2; shift 2;;
            ( -L|--load         ) load=$2; shift 2;;
            ( -D|--delete       ) delete=1; shift;;
        esac
    done
else
    shorthelp=1 # getopt returned (and reported) an error.
fi

ich erst jetzt Shell-Skripte schreiben und dann die und aus der Praxis fallen, so jedes Feedback ist willkommen.

Mit der vorgeschlagenen Strategie von @Arvid Requate, bemerkten wir einige Benutzerfehler. Ein Benutzer, der einen Wert enthalten vergisst haben versehentlich den Namen als Wert behandelt die nächste Option:

./getopts_test.sh --loglevel= --toc=TRUE

wird der Wert von „loglevel“ führen zu werden, wie gesehen „--toc = TRUE“. Das kann vermieden werden.

Ich angepasst einige Ideen über die Überprüfung Benutzerfehler für CLI von http://mwiki.wooledge.org/BashFAQ / 035 Diskussion der manuellen Analyse. I eingefügt Fehler in der Überprüfung sowohl die Handhabung „-“ und „-“ Argumente.

Dann begann ich, um mit der Syntax Hantieren, so hier irgendwelche Fehler sind streng meine Schuld, nicht die Original-Autoren.

Mein Ansatz hilft dem Anwender, die lange eingeben es vorziehen, mit oder ohne das Gleichheitszeichen. Das heißt, sollte es gleiche Antwort auf „--loglevel 9“ als „--loglevel = 9“ haben. In der - / Raum-Methode ist es nicht möglich, sicher zu wissen, ob der Benutzer ein Argument vergisst, so wird etwas zu raten benötigt.

  1. , wenn der Benutzer das lang / Gleichheitszeichen-Format (--opt =), dann ein Leerzeichen nach = einem Fehler auslöst, weil ein Argument nicht angegeben wurde.
  2. , wenn der Benutzer long / Raum Argumente (--opt) hat, dieses Skript bewirkt, dass ein fehlschlagen, wenn kein Argument (Ende des Befehls) folgt oder wenn Argument beginnt mit Bindestrich)

Falls Sie auf diese anfangen, gibt es einen interessanten Unterschied zwischen „--opt = value“ und „--opt Wert“ -Formate. Mit dem Gleichheitszeichen wird das Befehlszeilenargument als „opt = Wert“ gesehen und die Arbeit zu behandeln, die Zeichenfolgenanalyse ist, auf dem „=“ zu trennen. Im Gegensatz dazu mit „--opt Wert“, ist der Name des Arguments „opt“ und wir haben die Herausforderung, den nächsten Wert immer in der Befehlszeile angegeben. Das ist, wo @Arvid Requate $ verwendet {! OPTIND}, die indirekte Referenz. Ich verstehe immer noch nicht, dass, na ja, überhaupt, und Kommentare in BashFAQ gegen diesen Stil zu warnen scheinen ( http : //mywiki.wooledge.org/BashFAQ/006 ). Übrigens, ich glaube nicht, vorher bereits Kommentare über Bedeutung von OPTIND = $ ((OPTIND $ + 1)) korrekt sind. Ich will sagen, ich sehe keinen Schaden davon weggelassen wird.

In der neuesten Version dieses Skripts, Flag -v Ausführlich Ausdruck bedeutet.

Speichern Sie es in einer Datei namens „cli-5.sh“, macht ausführbare Datei, und jede von ihnen funktionieren wird, oder nicht in der gewünschten Weise

./cli-5.sh  -v --loglevel=44 --toc  TRUE
./cli-5.sh  -v --loglevel=44 --toc=TRUE
./cli-5.sh --loglevel 7
./cli-5.sh --loglevel=8
./cli-5.sh -l9

./cli-5.sh  --toc FALSE --loglevel=77
./cli-5.sh  --toc=FALSE --loglevel=77

./cli-5.sh   -l99 -t yyy
./cli-5.sh   -l 99 -t yyy

Hier ist Beispiel für die Ausgabe der Fehlerprüfung auf Benutzer intpu

$ ./cli-5.sh  --toc --loglevel=77
ERROR: toc value must not have dash at beginning
$ ./cli-5.sh  --toc= --loglevel=77
ERROR: value for toc undefined

Sie sollten prüfen auf -v drehen, weil es Interna von OPTIND ausdruckt und OPTARG

#/usr/bin/env bash

## Paul Johnson
## 20171016
##

## Combines ideas from
## https://stackoverflow.com/questions/402377/using-getopts-in-bash-shell-script-to-get-long-and-short-command-line-options
## by @Arvid Requate, and http://mwiki.wooledge.org/BashFAQ/035

# What I don't understand yet: 
# In @Arvid REquate's answer, we have 
# val="${!OPTIND}"; OPTIND=$(( $OPTIND + 1 ))
# this works, but I don't understand it!


die() {
    printf '%s\n' "$1" >&2
    exit 1
}

printparse(){
    if [ ${VERBOSE} -gt 0 ]; then
        printf 'Parse: %s%s%s\n' "$1" "$2" "$3" >&2;
    fi
}

showme(){
    if [ ${VERBOSE} -gt 0 ]; then
        printf 'VERBOSE: %s\n' "$1" >&2;
    fi
}


VERBOSE=0
loglevel=0
toc="TRUE"

optspec=":vhl:t:-:"
while getopts "$optspec" OPTCHAR; do

    showme "OPTARG:  ${OPTARG[*]}"
    showme "OPTIND:  ${OPTIND[*]}"
    case "${OPTCHAR}" in
        -)
            case "${OPTARG}" in
                loglevel) #argument has no equal sign
                    opt=${OPTARG}
                    val="${!OPTIND}"
                    ## check value. If negative, assume user forgot value
                    showme "OPTIND is {$OPTIND} {!OPTIND} has value \"${!OPTIND}\""
                    if [[ "$val" == -* ]]; then
                        die "ERROR: $opt value must not have dash at beginning"
                    fi
                    ## OPTIND=$(( $OPTIND + 1 )) # CAUTION! no effect?
                    printparse "--${OPTARG}" "  " "${val}"
                    loglevel="${val}"
                    shift
                    ;;
                loglevel=*) #argument has equal sign
                    opt=${OPTARG%=*}
                    val=${OPTARG#*=}
                    if [ "${OPTARG#*=}" ]; then
                        printparse "--${opt}" "=" "${val}"
                        loglevel="${val}"
                        ## shift CAUTION don't shift this, fails othewise
                    else
                        die "ERROR: $opt value must be supplied"
                    fi
                    ;;
                toc) #argument has no equal sign
                    opt=${OPTARG}
                    val="${!OPTIND}"
                    ## check value. If negative, assume user forgot value
                    showme "OPTIND is {$OPTIND} {!OPTIND} has value \"${!OPTIND}\""
                    if [[ "$val" == -* ]]; then
                        die "ERROR: $opt value must not have dash at beginning"
                    fi
                    ## OPTIND=$(( $OPTIND + 1 )) #??
                    printparse "--${opt}" " " "${val}"
                    toc="${val}"
                    shift
                    ;;
                toc=*) #argument has equal sign
                    opt=${OPTARG%=*}
                    val=${OPTARG#*=}
                    if [ "${OPTARG#*=}" ]; then
                        toc=${val}
                        printparse "--$opt" " -> " "$toc"
                        ##shift ## NO! dont shift this
                    else
                        die "ERROR: value for $opt undefined"
                    fi
                    ;;

                help)
                    echo "usage: $0 [-v] [--loglevel[=]<value>] [--toc[=]<TRUE,FALSE>]" >&2
                    exit 2
                    ;;
                *)
                    if [ "$OPTERR" = 1 ] && [ "${optspec:0:1}" != ":" ]; then
                        echo "Unknown option --${OPTARG}" >&2
                    fi
                    ;;
            esac;;
        h|-\?|--help)
            ## must rewrite this for all of the arguments
            echo "usage: $0 [-v] [--loglevel[=]<value>] [--toc[=]<TRUE,FALSE>]" >&2
            exit 2
            ;;
        l)
            loglevel=${OPTARG}
            printparse "-l" " "  "${loglevel}"
            ;;
        t)
            toc=${OPTARG}
            ;;
        v)
            VERBOSE=1
            ;;

        *)
            if [ "$OPTERR" != 1 ] || [ "${optspec:0:1}" = ":" ]; then
                echo "Non-option argument: '-${OPTARG}'" >&2
            fi
            ;;
    esac
done



echo "
After Parsing values
"
echo "loglevel  $loglevel" 
echo "toc  $toc"

Hier können Sie ein paar verschiedenen Ansätze für komplexe Option Parsing in bash finden: http://mywiki.wooledge.org/ComplexOptionParsing

Ich habe die folgenden erstellen, und ich denke, es ist ein guter, weil es minimal Code ist und sowohl Long- als auch Short-Optionen arbeiten. Eine lange Option kann auch mehrere Argumente mit diesem Ansatz hat.

#!/bin/bash
# Uses bash extensions.  Not portable as written.

declare -A longoptspec
longoptspec=( [loglevel]=1 ) #use associative array to declare how many arguments a long option expects, in this case we declare that loglevel expects/has one argument, long options that aren't listed i n this way will have zero arguments by default
optspec=":h-:"
while getopts "$optspec" opt; do
while true; do
    case "${opt}" in
        -) #OPTARG is name-of-long-option or name-of-long-option=value
            if [[ "${OPTARG}" =~ .*=.* ]] #with this --key=value format only one argument is possible
            then
                opt=${OPTARG/=*/}
                OPTARG=${OPTARG#*=}
                ((OPTIND--))    
            else #with this --key value1 value2 format multiple arguments are possible
                opt="$OPTARG"
                OPTARG=(${@:OPTIND:$((longoptspec[$opt]))})
            fi
            ((OPTIND+=longoptspec[$opt]))
            continue #now that opt/OPTARG are set we can process them as if getopts would've given us long options
            ;;
        loglevel)
          loglevel=$OPTARG
            ;;
        h|help)
            echo "usage: $0 [--loglevel[=]<value>]" >&2
            exit 2
            ;;
    esac
break; done
done

# End of file

Ich arbeite zu diesem Thema für eine recht lange Zeit ... und machte meine eigene Bibliothek, die Sie brauchen, um in Ihrem Haupt-Skript beziehen. Siehe libopt4shell und cd2mpc für ein Beispiel. Hoffe, es hilft!

Eine verbesserte Lösung:

# translate long options to short
# Note: This enable long options but disable "--?*" in $OPTARG, or disable long options after  "--" in option fields.
for ((i=1;$#;i++)) ; do
    case "$1" in
        --)
            # [ ${args[$((i-1))]} == ... ] || EndOpt=1 ;;& # DIRTY: we still can handle some execptions...
            EndOpt=1 ;;&
        --version) ((EndOpt)) && args[$i]="$1"  || args[$i]="-V";;
        # default case : short option use the first char of the long option:
        --?*) ((EndOpt)) && args[$i]="$1"  || args[$i]="-${1:2:1}";;
        # pass through anything else:
        *) args[$i]="$1" ;;
    esac
    shift
done
# reset the translated args
set -- "${args[@]}"

function usage {
echo "Usage: $0 [options] files" >&2
    exit $1
}

# now we can process with getopt
while getopts ":hvVc:" opt; do
    case $opt in
        h)  usage ;;
        v)  VERBOSE=true ;;
        V)  echo $Version ; exit ;;
        c)  source $OPTARG ;;
        \?) echo "unrecognized option: -$opt" ; usage -1 ;;
        :)
        echo "option -$OPTARG requires an argument"
        usage -1
        ;;
    esac
done

shift $((OPTIND-1))
[[ "$1" == "--" ]] && shift

Vielleicht ist es einfacher KSH zu bedienen, nur für den getopts Teil, wenn lange Befehlszeilenoptionen benötigen, wie kann es dort leichter durchgeführt werden.

# Working Getopts Long => KSH

#! /bin/ksh
# Getopts Long
USAGE="s(showconfig)"
USAGE+="c:(createdb)"
USAGE+="l:(createlistener)"
USAGE+="g:(generatescripts)"
USAGE+="r:(removedb)"
USAGE+="x:(removelistener)"
USAGE+="t:(createtemplate)"
USAGE+="h(help)"

while getopts "$USAGE" optchar ; do
    case $optchar in
    s)  echo "Displaying Configuration" ;;
        c)  echo "Creating Database $OPTARG" ;;
    l)  echo "Creating Listener LISTENER_$OPTARG" ;;
    g)  echo "Generating Scripts for Database $OPTARG" ;;
    r)  echo "Removing Database $OPTARG" ;;
    x)  echo "Removing Listener LISTENER_$OPTARG" ;;
    t)  echo "Creating Database Template" ;;
    h)  echo "Help" ;;
    esac
done

Ich habe noch nicht genug rep zu seiner Lösung zu kommentieren oder zu bewerten, aber sme Antwort funktionierte sehr gut für mich. Das einzige Problem, das ich führte, war in, dass die Argumente in einfache Anführungszeichen eingewickelt am Ende (also ich habe einen Streifen sie aus).

Ich habe auch einige Beispiele für den Gebrauch und Hilfetext. Ich werde meine leicht erweiterte Version hier enthalten:

#!/bin/bash

# getopt example
# from: https://stackoverflow.com/questions/402377/using-getopts-in-bash-shell-script-to-get-long-and-short-command-line-options
HELP_TEXT=\
"   USAGE:\n
    Accepts - and -- flags, can specify options that require a value, and can be in any order. A double-hyphen (--) will stop processing options.\n\n

    Accepts the following forms:\n\n

    getopt-example.sh -a -b -c value-for-c some-arg\n
    getopt-example.sh -c value-for-c -a -b some-arg\n
    getopt-example.sh -abc some-arg\n
    getopt-example.sh --along --blong --clong value-for-c -a -b -c some-arg\n
    getopt-example.sh some-arg --clong value-for-c\n
    getopt-example.sh
"

aflag=false
bflag=false
cargument=""

# options may be followed by one colon to indicate they have a required argument
if ! options=$(getopt -o abc:h\? -l along,blong,help,clong: -- "$@")
then
    # something went wrong, getopt will put out an error message for us
    exit 1
fi

set -- $options

while [ $# -gt 0 ]
do
    case $1 in
    -a|--along) aflag=true ;;
    -b|--blong) bflag=true ;;
    # for options with required arguments, an additional shift is required
    -c|--clong) cargument="$2" ; shift;;
    -h|--help|-\?) echo -e $HELP_TEXT; exit;;
    (--) shift; break;;
    (-*) echo "$0: error - unrecognized option $1" 1>&2; exit 1;;
    (*) break;;
    esac
    shift
done

# to remove the single quotes around arguments, pipe the output into:
# | sed -e "s/^'\\|'$//g"  (just leading/trailing) or | sed -e "s/'//g"  (all)

echo aflag=${aflag}
echo bflag=${bflag}
echo cargument=${cargument}

while [ $# -gt 0 ]
do
    echo arg=$1
    shift

    if [[ $aflag == true ]]; then
        echo a is true
    fi

done

Ich wollte etwas ohne externe Abhängigkeiten, mit strengen bash Unterstützung (-u), und ich brauchte es auch die älteren bash-Versionen zu arbeiten. Diese Griffe verschiedene Arten von params:

  • kurz bools (h)
  • Short-Optionen (-i "image.jpg")
  • long bools (--help)
  • gleich Optionen (--file = "filename.ext")
  • Raumoptionen (--file "filename.ext")
  • verkettet bools (-hvm)

Legen Sie einfach die folgenden am Anfang des Skripts:

# Check if a list of params contains a specific param
# usage: if _param_variant "h|?|help p|path f|file long-thing t|test-thing" "file" ; then ...
# the global variable $key is updated to the long notation (last entry in the pipe delineated list, if applicable)
_param_variant() {
  for param in $1 ; do
    local variants=${param//\|/ }
    for variant in $variants ; do
      if [[ "$variant" = "$2" ]] ; then
        # Update the key to match the long version
        local arr=(${param//\|/ })
        let last=${#arr[@]}-1
        key="${arr[$last]}"
        return 0
      fi
    done
  done
  return 1
}

# Get input parameters in short or long notation, with no dependencies beyond bash
# usage:
#     # First, set your defaults
#     param_help=false
#     param_path="."
#     param_file=false
#     param_image=false
#     param_image_lossy=true
#     # Define allowed parameters
#     allowed_params="h|?|help p|path f|file i|image image-lossy"
#     # Get parameters from the arguments provided
#     _get_params $*
#
# Parameters will be converted into safe variable names like:
#     param_help,
#     param_path,
#     param_file,
#     param_image,
#     param_image_lossy
#
# Parameters without a value like "-h" or "--help" will be treated as
# boolean, and will be set as param_help=true
#
# Parameters can accept values in the various typical ways:
#     -i "path/goes/here"
#     --image "path/goes/here"
#     --image="path/goes/here"
#     --image=path/goes/here
# These would all result in effectively the same thing:
#     param_image="path/goes/here"
#
# Concatinated short parameters (boolean) are also supported
#     -vhm is the same as -v -h -m
_get_params(){

  local param_pair
  local key
  local value
  local shift_count

  while : ; do
    # Ensure we have a valid param. Allows this to work even in -u mode.
    if [[ $# == 0 || -z $1 ]] ; then
      break
    fi

    # Split the argument if it contains "="
    param_pair=(${1//=/ })
    # Remove preceeding dashes
    key="${param_pair[0]#--}"

    # Check for concatinated boolean short parameters.
    local nodash="${key#-}"
    local breakout=false
    if [[ "$nodash" != "$key" && ${#nodash} -gt 1 ]]; then
      # Extrapolate multiple boolean keys in single dash notation. ie. "-vmh" should translate to: "-v -m -h"
      local short_param_count=${#nodash}
      let new_arg_count=$#+$short_param_count-1
      local new_args=""
      # $str_pos is the current position in the short param string $nodash
      for (( str_pos=0; str_pos<new_arg_count; str_pos++ )); do
        # The first character becomes the current key
        if [ $str_pos -eq 0 ] ; then
          key="${nodash:$str_pos:1}"
          breakout=true
        fi
        # $arg_pos is the current position in the constructed arguments list
        let arg_pos=$str_pos+1
        if [ $arg_pos -gt $short_param_count ] ; then
          # handle other arguments
          let orignal_arg_number=$arg_pos-$short_param_count+1
          local new_arg="${!orignal_arg_number}"
        else
          # break out our one argument into new ones
          local new_arg="-${nodash:$str_pos:1}"
        fi
        new_args="$new_args \"$new_arg\""
      done
      # remove the preceding space and set the new arguments
      eval set -- "${new_args# }"
    fi
    if ! $breakout ; then
      key="$nodash"
    fi

    # By default we expect to shift one argument at a time
    shift_count=1
    if [ "${#param_pair[@]}" -gt "1" ] ; then
      # This is a param with equals notation
      value="${param_pair[1]}"
    else
      # This is either a boolean param and there is no value,
      # or the value is the next command line argument
      # Assume the value is a boolean true, unless the next argument is found to be a value.
      value=true
      if [[ $# -gt 1 && -n "$2" ]]; then
        local nodash="${2#-}"
        if [ "$nodash" = "$2" ]; then
          # The next argument has NO preceding dash so it is a value
          value="$2"
          shift_count=2
        fi
      fi
    fi

    # Check that the param being passed is one of the allowed params
    if _param_variant "$allowed_params" "$key" ; then
      # --key-name will now become param_key_name
      eval param_${key//-/_}="$value"
    else
      printf 'WARNING: Unknown option (ignored): %s\n' "$1" >&2
    fi
    shift $shift_count
  done
}

Und verwenden Sie es wie folgt:

# Assign defaults for parameters
param_help=false
param_path=$(pwd)
param_file=false
param_image=true
param_image_lossy=true
param_image_lossy_quality=85

# Define the params we will allow
allowed_params="h|?|help p|path f|file i|image image-lossy image-lossy-quality"

# Get the params from arguments provided
_get_params $*

Die akzeptierte Antwort hat eine sehr schöne Aufgabe, darauf hinzuweisen, alle Mängel der bash eingebauten in getopts. Die Antwort endet mit:

  

So, während es möglich ist, mehr Code zu schreiben, um den Mangel an Unterstützung für lange Optionen zu arbeiten, das viel mehr Arbeit ist und besiegt teilweise den Zweck, einen getopt Parser verwenden Sie den Code zu vereinfachen.

Und obwohl ich grundsätzlich mit dieser Aussage zustimmen, ich glaube, dass die Anzahl der Male, die wir alles diese Funktion in verschiedenen Skripten implementiert rechtfertigt ein wenig Mühe Indienststellung eine „standardisierte“, erprobte Lösung.

Als solche habe ich "aufgerüstet" bash in getopts gebaut durch die Implementierung von https://github.com/UmkaDK/getopts_long) in einem Skript, kann die Antwort auf die ursprüngliche Frage implementiert wird so einfach wie:

source "${PATH_TO}/getopts_long.bash"

while getopts_long ':c: copyfile:' OPTKEY; do
    case ${OPTKEY} in
        'c'|'copyfile')
            echo 'file supplied -- ${OPTARG}'
            ;;
        '?')
            echo "INVALID OPTION -- ${OPTARG}" >&2
            exit 1
            ;;
        ':')
            echo "MISSING ARGUMENT for option -- ${OPTARG}" >&2
            exit 1
            ;;
        *)
            echo "Misconfigured OPTSPEC or uncaught option -- ${OPTKEY}" >&2
            exit 1
            ;;
    esac
done

shift $(( OPTIND - 1 ))
[[ "${1}" == "--" ]] && shift

Um Cross-Plattform-kompatibel zu bleiben, und vermeiden die Abhängigkeit von externen ausführbaren Dateien, portierte ich einige Codes aus einer anderen Sprache.

ich es sehr einfach für Sie zu nutzen, ist hier ein Beispiel:

ArgParser::addArg "[h]elp"    false    "This list"
ArgParser::addArg "[q]uiet"   false    "Supress output"
ArgParser::addArg "[s]leep"   1        "Seconds to sleep"
ArgParser::addArg "v"         1        "Verbose mode"

ArgParser::parse "$@"

ArgParser::isset help && ArgParser::showArgs

ArgParser::isset "quiet" \
   && echo "Quiet!" \
   || echo "Noisy!"

local __sleep
ArgParser::tryAndGetArg sleep into __sleep \
   && echo "Sleep for $__sleep seconds" \
   || echo "No value passed for sleep"

# This way is often more convienient, but is a little slower
echo "Sleep set to: $( ArgParser::getArg sleep )"

Die erforderliche BASH ist ein wenig länger als es sein könnte, aber ich wollte BASH 4 Vertrauen auf assoziativen Arrays vermeiden. Sie können dies auch direkt herunterladen von http://nt4.com/bash/argparser.inc.sh

#!/usr/bin/env bash

# Updates to this script may be found at
# http://nt4.com/bash/argparser.inc.sh

# Example of runtime usage:
# mnc.sh --nc -q Caprica.S0*mkv *.avi *.mp3 --more-options here --host centos8.host.com

# Example of use in script (see bottom)
# Just include this file in yours, or use
# source argparser.inc.sh

unset EXPLODED
declare -a EXPLODED
function explode 
{
    local c=$# 
    (( c < 2 )) && 
    {
        echo function "$0" is missing parameters 
        return 1
    }

    local delimiter="$1"
    local string="$2"
    local limit=${3-99}

    local tmp_delim=$'\x07'
    local delin=${string//$delimiter/$tmp_delim}
    local oldifs="$IFS"

    IFS="$tmp_delim"
    EXPLODED=($delin)
    IFS="$oldifs"
}


# See: http://fvue.nl/wiki/Bash:_Passing_variables_by_reference
# Usage: local "$1" && upvar $1 "value(s)"
upvar() {
    if unset -v "$1"; then           # Unset & validate varname
        if (( $# == 2 )); then
            eval $1=\"\$2\"          # Return single value
        else
            eval $1=\(\"\${@:2}\"\)  # Return array
        fi
    fi
}

function decho
{
    :
}

function ArgParser::check
{
    __args=${#__argparser__arglist[@]}
    for (( i=0; i<__args; i++ ))
    do
        matched=0
        explode "|" "${__argparser__arglist[$i]}"
        if [ "${#1}" -eq 1 ]
        then
            if [ "${1}" == "${EXPLODED[0]}" ]
            then
                decho "Matched $1 with ${EXPLODED[0]}"
                matched=1

                break
            fi
        else
            if [ "${1}" == "${EXPLODED[1]}" ]
            then
                decho "Matched $1 with ${EXPLODED[1]}"
                matched=1

                break
            fi
        fi
    done
    (( matched == 0 )) && return 2
    # decho "Key $key has default argument of ${EXPLODED[3]}"
    if [ "${EXPLODED[3]}" == "false" ]
    then
        return 0
    else
        return 1
    fi
}

function ArgParser::set
{
    key=$3
    value="${1:-true}"
    declare -g __argpassed__$key="$value"
}

function ArgParser::parse
{

    unset __argparser__argv
    __argparser__argv=()
    # echo parsing: "$@"

    while [ -n "$1" ]
    do
        # echo "Processing $1"
        if [ "${1:0:2}" == '--' ]
        then
            key=${1:2}
            value=$2
        elif [ "${1:0:1}" == '-' ]
        then
            key=${1:1}               # Strip off leading -
            value=$2
        else
            decho "Not argument or option: '$1'" >& 2
            __argparser__argv+=( "$1" )
            shift
            continue
        fi
        # parameter=${tmp%%=*}     # Extract name.
        # value=${tmp##*=}         # Extract value.
        decho "Key: '$key', value: '$value'"
        # eval $parameter=$value
        ArgParser::check $key
        el=$?
        # echo "Check returned $el for $key"
        [ $el -eq  2 ] && decho "No match for option '$1'" >&2 # && __argparser__argv+=( "$1" )
        [ $el -eq  0 ] && decho "Matched option '${EXPLODED[2]}' with no arguments"        >&2 && ArgParser::set true "${EXPLODED[@]}"
        [ $el -eq  1 ] && decho "Matched option '${EXPLODED[2]}' with an argument of '$2'"   >&2 && ArgParser::set "$2" "${EXPLODED[@]}" && shift
        shift
    done
}

function ArgParser::isset
{
    declare -p "__argpassed__$1" > /dev/null 2>&1 && return 0
    return 1
}

function ArgParser::getArg
{
    # This one would be a bit silly, since we can only return non-integer arguments ineffeciently
    varname="__argpassed__$1"
    echo "${!varname}"
}

##
# usage: tryAndGetArg <argname> into <varname>
# returns: 0 on success, 1 on failure
function ArgParser::tryAndGetArg
{
    local __varname="__argpassed__$1"
    local __value="${!__varname}"
    test -z "$__value" && return 1
    local "$3" && upvar $3 "$__value"
    return 0
}

function ArgParser::__construct
{
    unset __argparser__arglist
    # declare -a __argparser__arglist
}

##
# @brief add command line argument
# @param 1 short and/or long, eg: [s]hort
# @param 2 default value
# @param 3 description
##
function ArgParser::addArg
{
    # check for short arg within long arg
    if [[ "$1" =~ \[(.)\] ]]
    then
        short=${BASH_REMATCH[1]}
        long=${1/\[$short\]/$short}
    else
        long=$1
    fi
    if [ "${#long}" -eq 1 ]
    then
        short=$long
        long=''
    fi
    decho short: "$short"
    decho long: "$long"
    __argparser__arglist+=("$short|$long|$1|$2|$3")
}

## 
# @brief show available command line arguments
##
function ArgParser::showArgs
{
    # declare -p | grep argparser
    printf "Usage: %s [OPTION...]\n\n" "$( basename "${BASH_SOURCE[0]}" )"
    printf "Defaults for the options are specified in brackets.\n\n";

    __args=${#__argparser__arglist[@]}
    for (( i=0; i<__args; i++ ))
    do
        local shortname=
        local fullname=
        local default=
        local description=
        local comma=

        explode "|" "${__argparser__arglist[$i]}"

        shortname="${EXPLODED[0]:+-${EXPLODED[0]}}" # String Substitution Guide: 
        fullname="${EXPLODED[1]:+--${EXPLODED[1]}}" # http://tldp.org/LDP/abs/html/parameter-substitution.html
        test -n "$shortname" \
            && test -n "$fullname" \
            && comma=","

        default="${EXPLODED[3]}"
        case $default in
            false )
                default=
                ;;
            "" )
                default=
                ;;
            * )
                default="[$default]"
        esac

        description="${EXPLODED[4]}"

        printf "  %2s%1s %-19s %s %s\n" "$shortname" "$comma" "$fullname" "$description" "$default"
    done
}

function ArgParser::test
{
    # Arguments with a default of 'false' do not take paramaters (note: default
    # values are not applied in this release)

    ArgParser::addArg "[h]elp"      false       "This list"
    ArgParser::addArg "[q]uiet" false       "Supress output"
    ArgParser::addArg "[s]leep" 1           "Seconds to sleep"
    ArgParser::addArg "v"           1           "Verbose mode"

    ArgParser::parse "$@"

    ArgParser::isset help && ArgParser::showArgs

    ArgParser::isset "quiet" \
        && echo "Quiet!" \
        || echo "Noisy!"

    local __sleep
    ArgParser::tryAndGetArg sleep into __sleep \
        && echo "Sleep for $__sleep seconds" \
        || echo "No value passed for sleep"

    # This way is often more convienient, but is a little slower
    echo "Sleep set to: $( ArgParser::getArg sleep )"

    echo "Remaining command line: ${__argparser__argv[@]}"

}

if [ "$( basename "$0" )" == "argparser.inc.sh" ]
then
    ArgParser::test "$@"
fi

Wenn alle Ihrer langen Optionen haben einzigartiges und Matching, erste Zeichen wie die kurzen Optionen, so zum Beispiel

./slamm --chaos 23 --plenty test -quiet

Ist das gleiche wie

./slamm -c 23 -p test -q

Sie können diese verwenden vor getopts $ args neu zu schreiben:

# change long options to short options

for arg; do 
    [[ "${arg:0:1}" == "-" ]] && delim="" || delim="\""
    if [ "${arg:0:2}" == "--" ]; 
       then args="${args} -${arg:2:1}" 
       else args="${args} ${delim}${arg}${delim}"
    fi
done

# reset the incoming args
eval set -- $args

# proceed as usual
while getopts ":b:la:h" OPTION; do
    .....

Danke für mtvee für die Inspiration; -)

Builtin getopts nur kurze Optionen analysieren (außer in ksh93), Sie können jedoch noch einige Zeilen von Scripting in den getopts Griffe lange Optionen zu machen.

Hier ist ein Teil des Codes gefunden in http://www.uxora.com/unix/shell-script/22-handle-long-options-with-getopts

  #== set short options ==#
SCRIPT_OPTS=':fbF:B:-:h'
  #== set long options associated with short one ==#
typeset -A ARRAY_OPTS
ARRAY_OPTS=(
    [foo]=f
    [bar]=b
    [foobar]=F
    [barfoo]=B
    [help]=h
    [man]=h
)

  #== parse options ==#
while getopts ${SCRIPT_OPTS} OPTION ; do
    #== translate long options to short ==#
    if [[ "x$OPTION" == "x-" ]]; then
        LONG_OPTION=$OPTARG
        LONG_OPTARG=$(echo $LONG_OPTION | grep "=" | cut -d'=' -f2)
        LONG_OPTIND=-1
        [[ "x$LONG_OPTARG" = "x" ]] && LONG_OPTIND=$OPTIND || LONG_OPTION=$(echo $OPTARG | cut -d'=' -f1)
        [[ $LONG_OPTIND -ne -1 ]] && eval LONG_OPTARG="\$$LONG_OPTIND"
        OPTION=${ARRAY_OPTS[$LONG_OPTION]}
        [[ "x$OPTION" = "x" ]] &&  OPTION="?" OPTARG="-$LONG_OPTION"

        if [[ $( echo "${SCRIPT_OPTS}" | grep -c "${OPTION}:" ) -eq 1 ]]; then
            if [[ "x${LONG_OPTARG}" = "x" ]] || [[ "${LONG_OPTARG}" = -* ]]; then 
                OPTION=":" OPTARG="-$LONG_OPTION"
            else
                OPTARG="$LONG_OPTARG";
                if [[ $LONG_OPTIND -ne -1 ]]; then
                    [[ $OPTIND -le $Optnum ]] && OPTIND=$(( $OPTIND+1 ))
                    shift $OPTIND
                    OPTIND=1
                fi
            fi
        fi
    fi

    #== options follow by another option instead of argument ==#
    if [[ "x${OPTION}" != "x:" ]] && [[ "x${OPTION}" != "x?" ]] && [[ "${OPTARG}" = -* ]]; then 
        OPTARG="$OPTION" OPTION=":"
    fi

    #== manage options ==#
    case "$OPTION" in
        f  ) foo=1 bar=0                    ;;
        b  ) foo=0 bar=1                    ;;
        B  ) barfoo=${OPTARG}               ;;
        F  ) foobar=1 && foobar_name=${OPTARG} ;;
        h ) usagefull && exit 0 ;;
        : ) echo "${SCRIPT_NAME}: -$OPTARG: option requires an argument" >&2 && usage >&2 && exit 99 ;;
        ? ) echo "${SCRIPT_NAME}: -$OPTARG: unknown option" >&2 && usage >&2 && exit 99 ;;
    esac
done
shift $((${OPTIND} - 1))

Hier ist ein Test:

# Short options test
$ ./foobar_any_getopts.sh -bF "Hello world" -B 6 file1 file2
foo=0 bar=1
barfoo=6
foobar=1 foobar_name=Hello world
files=file1 file2

# Long and short options test
$ ./foobar_any_getopts.sh --bar -F Hello --barfoo 6 file1 file2
foo=0 bar=1
barfoo=6
foobar=1 foobar_name=Hello
files=file1 file2

Ansonsten in den letzten Korn Shell ksh93, getopts können lange Optionen natürlich analysieren und sogar einen Mann Seite gleich angezeigt werden soll. (Siehe http: // www .uxora.com / Unix / Shell-Skript / 20-getopts-mit-Mann-Seite-and-long-Optionen )

Th integrierte OS X (BSD) getopt unterstützt keine langen Optionen, aber die GNU-Version tut: brew install gnu-getopt. Dann etwas Ähnliches wie:. cp /usr/local/Cellar/gnu-getopt/1.1.6/bin/getopt /usr/local/bin/gnu-getopt

EasyOptions behandelt kurze und lange Optionen:

## Options:
##   --verbose, -v   Verbose mode
##   --logfile=NAME  Log filename

source easyoptions || exit

if test -n "${verbose}"; then
    echo "log file: ${logfile}"
    echo "arguments: ${arguments[@]}"
fi

Ein einfaches DIY bekommen nur lange Namen args:

Verwendung:

$ ./test-args.sh --a1 a1 --a2 "a 2" --a3 --a4= --a5=a5 --a6="a 6"
a1 = "a1"
a2 = "a 2"
a3 = "TRUE"
a4 = ""
a5 = "a5"
a6 = "a 6"
a7 = ""

Script:

#!/bin/bash

function main() {
    ARGS=`getArgs "$@"`

    a1=`echo "$ARGS" | getNamedArg a1`
    a2=`echo "$ARGS" | getNamedArg a2`
    a3=`echo "$ARGS" | getNamedArg a3`
    a4=`echo "$ARGS" | getNamedArg a4`
    a5=`echo "$ARGS" | getNamedArg a5`
    a6=`echo "$ARGS" | getNamedArg a6`
    a7=`echo "$ARGS" | getNamedArg a7`

    echo "a1 = \"$a1\""
    echo "a2 = \"$a2\""
    echo "a3 = \"$a3\""
    echo "a4 = \"$a4\""
    echo "a5 = \"$a5\""
    echo "a6 = \"$a6\""
    echo "a7 = \"$a7\""

    exit 0
}


function getArgs() {
    for arg in "$@"; do
        echo "$arg"
    done
}


function getNamedArg() {
    ARG_NAME=$1

    sed --regexp-extended --quiet --expression="
        s/^--$ARG_NAME=(.*)\$/\1/p  # Get arguments in format '--arg=value': [s]ubstitute '--arg=value' by 'value', and [p]rint
        /^--$ARG_NAME\$/ {          # Get arguments in format '--arg value' ou '--arg'
            n                       # - [n]ext, because in this format, if value exists, it will be the next argument
            /^--/! p                # - If next doesn't starts with '--', it is the value of the actual argument
            /^--/ {                 # - If next do starts with '--', it is the next argument and the actual argument is a boolean one
                # Then just repla[c]ed by TRUE
                c TRUE
            }
        }
    "
}


main "$@"

, wenn einfach das ist, wie Sie das Skript aufrufen

myscript.sh --input1 "ABC" --input2 "PQR" --input2 "XYZ"

dann können Sie diese einfachste Art und Weise folgen sie mit Hilfe von getopt zu erreichen und --longoptions

versuchen dies, hoffen, dass dies sinnvoll ist

# Read command line options
ARGUMENT_LIST=(
    "input1"
    "input2"
    "input3"
)



# read arguments
opts=$(getopt \
    --longoptions "$(printf "%s:," "${ARGUMENT_LIST[@]}")" \
    --name "$(basename "$0")" \
    --options "" \
    -- "$@"
)


echo $opts

eval set --$opts

while true; do
    case "$1" in
    --input1)  
        shift
        empId=$1
        ;;
    --input2)  
        shift
        fromDate=$1
        ;;
    --input3)  
        shift
        toDate=$1
        ;;
      --)
        shift
        break
        ;;
    esac
    shift
done
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top