Ich habe eine ähnliche POSIX-Funktion geschrieben, aber dies riskiert keine willkürliche Codeausführung:
unexport()
while case ${1##[0-9]*} in ### rule out leading numerics
(*[!_[:alnum:]]*|"") ### filter out bad|empty names
set "" ${1+"bad name: '$1'"} ### prep bad name error
return ${2+${1:?"$2"}} ### fail w/ above err or return
esac
do eval set '"$'"{$1+$1}"'" "$'"$1"'" "$'@\" ### $1 = ( $1+ ? $1 : "" )
eval "${1:+unset $1;$1=\$2;} shift 3" ### $$1 = ( $1:+ ? $2 : -- )
done
Es werden auch so viele Argumente verarbeitet, wie Sie möchten. Wenn ein Argument ein gültiger Name ist, der nicht bereits festgelegt wurde, wird es stillschweigend ignoriert. Wenn ein Argument ein falscher Name ist, schreibt es in stderr und hält entsprechend an, obwohl jeder gültige Name, der in der Befehlszeile vor einem ungültigen Namen steht, weiterhin verarbeitet wird.
Ich dachte an einen anderen Weg. Ich mag es viel besser.
unexport()
while unset OPTARG; OPTIND=1 ### always work w/ $1
case ${1##[0-9]*} in ### same old same old
(*[!_[:alnum:]]*|"") ### goodname && $# > 0 || break
${1+"getopts"} : "$1" ### $# ? getopts : ":"
return ### getopts errored or ":" didnt
esac
do eval getopts :s: '"$1" -"${'"$1+s}-\$$1\""
eval unset "$1; ${OPTARG+$1=\${OPTARG}#-}"
shift
done
Nun, beide verwenden viele der gleichen Techniken. Wenn eine Shell-Variable nicht gesetzt ist, wird ein Verweis darauf nicht mit einer +Parametererweiterung erweitert. Wenn es jedoch - unabhängig von seinem Wert - festgelegt ist, wird eine Parametererweiterung wie: ${parameter+word}auf word- und nicht auf den Wert der Variablen erweitert. Und so testen sich Shell-Variablen beim Erfolg selbst und ersetzen sie selbst.
Sie können auch selbst versagen . Wenn in der obersten Funktion ein falscher Name gefunden wird, gehe ich $1zu null $2und lasse $1null, da das nächste, was ich mache, entweder returnErfolg ist, wenn alle Argumente verarbeitet wurden und die Schleife beendet ist, oder wenn das Argument ungültig war, wird die Shell dies tun Erweitern Sie das, $2in $1:?das eine Skript-Shell beendet wird, und geben Sie beim Schreiben wordan stderr einen Interrupt an einen interaktiven zurück .
Im zweiten getoptserledigt man die Aufgaben. Und es wird kein schlechter Name zugewiesen - stattdessen wird eine Standardfehlermeldung an stderr geschrieben. Außerdem wird der Wert des Args gespeichert, $OPTARG wenn das Argument in erster Linie der Name einer festgelegten Variablen war. Nachdem Sie dies getan getoptshaben, müssen Sie lediglich die evalMenge eines Sets OPTARGin die entsprechende Zuordnung erweitern.
mktempwenn das tragbare genug ist, und unset den Wert und Quelle die temporäre Datei die Variable zuzuweisen. Im Gegensatz zu einer Shell-Variablen kann zumindest eine temporäre Datei mit einem mehr oder weniger beliebigen Namen erstellt werden.