Escribí una función POSIX similar, pero esto no arriesga la ejecución de código arbitrario:
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
También manejará tantos argumentos como desee para proporcionarlo. Si un argumento es un nombre válido que de otro modo no está establecido, se ignora en silencio. Si un argumento es un nombre incorrecto, escribe en stderr y se detiene según corresponda, aunque cualquier nombre válido que precede a un inválido en su línea de comando aún se procesará.
Pensé en otra forma. Me gusta mucho mejor.
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
Bueno, ambos usan muchas de las mismas técnicas. Básicamente, si un shell var está desarmado, una referencia a él no se expandirá con una +
expansión de parámetros. Pero si se establece, independientemente de su valor, una expansión de parámetros como: ${parameter+word}
se expandirá a word
, y no al valor de la variable. Y así, las variables de shell se autoevalúan y sustituyen automáticamente en caso de éxito.
También pueden fallar a sí mismos . En la función de la parte superior si un nombre mal se encuentra muevo $1
en $2
y la licencia $1
nula debido a que el siguiente que hago es o bien return
el éxito si todos los argumentos han sido procesados y el bucle llega a su fin, o, si el arg no era válida, el shell ampliar la $2
en $1:?
que matará a una concha con guión y devolver una interrupción de un interactivo al escribir word
en stderr.
En el segundo getopts
hace las tareas. Y no asignará un nombre incorrecto, más bien escribirlo escribirá un mensaje de error estándar para stderr. Además, guarda el valor del argumento $OPTARG
si el argumento era el nombre de una variable establecida en primer lugar. Entonces, después de hacer getopts
todo lo que se necesita es la expansión de eval
un conjunto OPTARG
en la asignación apropiada.
mktemp
si es que es lo suficientemente portátil, y desarmar el valor, y la fuente del archivo temporal para asignar la variable. Al menos se puede crear un archivo temporal con un nombre más o menos arbitrario en contraste con una variable de shell.