Ich weiß, dass dies bereits beantwortet wurde, aber der Vollständigkeit halber und für alle mit denselben Anforderungen wie ich habe ich beschlossen, diese verwandte Antwort zu veröffentlichen. Der Code ist mit Kommentaren übersät, um den Code zu erklären.
Aktualisierte Antwort:
Speichern Sie die Datei als getopt.sh
:
#!/bin/bash
function get_variable_name_for_option {
local OPT_DESC=${1}
local OPTION=${2}
local VAR=$(echo ${OPT_DESC} | sed -e "s/.*\[\?-${OPTION} \([A-Z_]\+\).*/\1/g" -e "s/.*\[\?-\(${OPTION}\).*/\1FLAG/g")
if [[ "${VAR}" == "${1}" ]]; then
echo ""
else
echo ${VAR}
fi
}
function parse_options {
local OPT_DESC=${1}
local INPUT=$(get_input_for_getopts "${OPT_DESC}")
shift
while getopts ${INPUT} OPTION ${@};
do
[ ${OPTION} == "?" ] && usage
VARNAME=$(get_variable_name_for_option "${OPT_DESC}" "${OPTION}")
[ "${VARNAME}" != "" ] && eval "${VARNAME}=${OPTARG:-true}" # && printf "\t%s\n" "* Declaring ${VARNAME}=${!VARNAME} -- OPTIONS='$OPTION'"
done
check_for_required "${OPT_DESC}"
}
function check_for_required {
local OPT_DESC=${1}
local REQUIRED=$(get_required "${OPT_DESC}" | sed -e "s/\://g")
while test -n "${REQUIRED}"; do
OPTION=${REQUIRED:0:1}
VARNAME=$(get_variable_name_for_option "${OPT_DESC}" "${OPTION}")
[ -z "${!VARNAME}" ] && printf "ERROR: %s\n" "Option -${OPTION} must been set." && usage
REQUIRED=${REQUIRED:1}
done
}
function get_input_for_getopts {
local OPT_DESC=${1}
echo ${OPT_DESC} | sed -e "s/\([a-zA-Z]\) [A-Z_]\+/\1:/g" -e "s/[][ -]//g"
}
function get_optional {
local OPT_DESC=${1}
echo ${OPT_DESC} | sed -e "s/[^[]*\(\[[^]]*\]\)[^[]*/\1/g" -e "s/\([a-zA-Z]\) [A-Z_]\+/\1:/g" -e "s/[][ -]//g"
}
function get_required {
local OPT_DESC=${1}
echo ${OPT_DESC} | sed -e "s/\([a-zA-Z]\) [A-Z_]\+/\1:/g" -e "s/\[[^[]*\]//g" -e "s/[][ -]//g"
}
function usage {
printf "Verwendung:\n\t%s\n" "${0} ${OPT_DESC}"
exit 10
}
Dann können Sie es so verwenden:
#!/bin/bash
#
# [ und ] definieren optionale Argumente
#
# Speicherort der getopts.sh Datei
quelle ./getopt.sh
USAGE="-u BENUTZER -d DATENBANK -p PASS -s SID [ -a START_DATUM_ZEIT ]"
parse_options "${USAGE}" ${@}
echo ${BENUTZER}
echo ${START_DATUM_ZEIT}
Alte Antwort:
Ich musste kürzlich einen generischen Ansatz verwenden. Ich stieß auf diese Lösung:
#!/bin/bash
# Option Beschreibung:
# -------------------
#
# Die Option Beschreibung basiert auf dem eingebauten getopts-Befehl von bash. Die Beschreibung fügt eine Funktion zur Variablennamen hinzu, die in Zukunft zur Prüfung von erforderlichen oder optionalen Werten verwendet werden kann.
# Die Option Beschreibung fügt den String "=>VARIABLE_NAME" hinzu. Der Variablenname sollte GROßBUCHSTABEN sein. Gültige Zeichen sind [A-Z_]*.
#
# Ein Beispiel für eine Optionsbeschreibung:
# OPT_DESC="a:=>A_VARIABLE|b:=>B_VARIABLE|c=>C_VARIABLE"
#
# -a-Option erfordert einen Wert (das Doppelpunkt bedeutet das) und sollte in der Variablen A_VARIABLE gespeichert werden.
# "|" wird verwendet, um die Optionsbeschreibung zu trennen.
# Die Regel der -b-Option ist dieselbe wie bei -a.
# Die -c-Option erfordert keinen Wert (das Fehlen des Doppelpunkts bedeutet dies) und ihre Existenz sollte in C_VARIABLE festgelegt werden.
#
# ~$ echo get_options ${OPT_DESC}
# a:b:c
# ~$
#
# Erforderliche Optionen
REQUIRED_DESC="a:=>REQ_A_VAR_VALUE|B:=>REQ_B_VAR_VALUE|c=>REQ_C_VAR_FLAG"
# Optionale Optionen (duh)
OPTIONAL_DESC="P:=>OPT_P_VAR_VALUE|r=>OPT_R_VAR_FLAG"
function usage {
IFS="|"
printf "%s" ${0}
for i in ${REQUIRED_DESC};
do
VARNAME=$(echo $i | sed -e "s/.*=>//g")
printf " %s" "-${i:0:1} $VARNAME"
done
for i in ${OPTIONAL_DESC};
do
VARNAME=$(echo $i | sed -e "s/.*=>//g")
printf " %s" "[-${i:0:1} $VARNAME]"
done
printf "\n"
unset IFS
exit
}
# Hilfsfunktion, die die Optionen characters zurückgibt, die an 'getopts' aus einer Optionsbeschreibung übergeben werden sollen.
# Argumente:
# $1: Die Optionenbeschreibung (SIEHE OBEN)
#
# Beispiel:
# OPT_DESC="h:=>H_VAR|f:=>F_VAR|P=>P_VAR|W=>W_VAR"
# OPTIONS=$(get_options ${OPT_DESC})
# echo "${OPTIONS}"
#
# Ausgang:
# "h:f:PW"
function get_options {
echo ${1} | sed -e "s/\([a-zA-Z]\:\?\)=>[A-Z_]*|\?/\1/g"
}
# Hilfsfunktion, die alle Variablennamen durch '|' getrennt zurückgibt
# Argumente:
# $1: Die Optionenbeschreibung (SIEHE OBEN)
#
# Beispiel:
# OPT_DESC="h:=>H_VAR|f:=>F_VAR|P=>P_VAR|W=>W_VAR"
# VARNAMES=$(get_values ${OPT_DESC})
# echo "${VARNAMES}"
#
# Ausgang:
# "H_VAR|F_VAR|P_VAR|W_VAR"
function get_variables {
echo ${1} | sed -e "s/[a-zA-Z]\:\?=>\([^|]*\)/\1/g"
}
# Hilfsfunktion, die den Variablennamen basierend auf dem
# übergebenen Option den Variablennamen zurückgibt.
# Argumente:
# $1: Die Optionenbeschreibung (SIEHE OBEN)
# $2: Die Option, für die der Variablenname abgerufen werden soll
#
# Beispiel:
# OPT_DESC="h:=>H_VAR|f:=>F_VAR|P=>P_VAR|W=>W_VAR"
# H_VAR=$(get_variable_name ${OPT_DESC} "h")
# echo "${H_VAR}"
#
# Ausgang:
# "H_VAR"
function get_variable_name {
VAR=$(echo ${1} | sed -e "s/.*${2}\:\?=>\([^|]*\).*/\1/g")
if [[ ${VAR} == ${1} ]]; then
echo ""
else
echo ${VAR}
fi
}
# Holt die erforderlichen Optionen aus der erforderlichen Beschreibung
REQUIRED=$(get_options ${REQUIRED_DESC})
# Holt die optionalen Optionen (duh) aus der optionalen Beschreibung
OPTIONAL=$(get_options ${OPTIONAL_DESC})
# oder... $(get_options "${OPTIONAL_DESC}|${REQUIRED_DESC}")
# Der Doppelpunkt am Anfang weist getopts an, still zu bleiben
while getopts ":${REQUIRED}${OPTIONAL}" OPTION
do
[[ ${OPTION} == ":" ]] && usage
VAR=$(get_variable_name "${REQUIRED_DESC}|${OPTIONAL_DESC}" ${OPTION})
[[ -n ${VAR} ]] && eval "$VAR=${OPTARG}"
done
shift $(($OPTIND - 1))
# Überprüft erforderliche Optionen. Gibt einen Fehler aus und beendet, falls
# erforderliche Optionen fehlen.
# Verwendung der Funktionsversion ...
VARS=$(get_variables ${REQUIRED_DESC})
IFS="|"
for VARNAME in $VARS;
do
[[ -v ${VARNAME} ]] || usage
done
unset IFS
# ... oder Verwendung der IFS-Version (ohne Funktion)
OLDIFS=${IFS}
IFS="|"
for i in ${REQUIRED_DESC};
do
VARNAME=$(echo $i | sed -e "s/.*=>//g")
[[ -v ${VARNAME} ]] || usage
printf "%s %s %s\n" "-${i:0:1}" "${!VARNAME:=present}" "${VARNAME}"
done
IFS=${OLDIFS}
Ich habe dies nicht gründlich getestet, daher könnten einige Fehler darin sein.