Eu escrevi uma função POSIX semelhante, mas isso não corre o risco de execução arbitrária de código:
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
Ele também manipulará quantos argumentos você desejar para fornecê-lo. Se um argumento for um nome válido que ainda não está definido, ele será ignorado silenciosamente. Se um argumento é um nome ruim, ele grava no stderr e pára conforme o apropriado, embora qualquer nome válido anterior a um inválido em sua linha de comando ainda seja processado.
Eu pensei em outro caminho. Eu gosto muito melhor.
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
Bem, ambos usam muitas das mesmas técnicas. Basicamente, se um shell var estiver desativado, uma referência a ele não será expandida com uma +
expansão de parâmetro. Mas se estiver definido - independentemente do seu valor -, uma expansão de parâmetro como: ${parameter+word}
será expandida para word
- e não para o valor da variável. E assim, as variáveis de shell são testadas e substituídas com êxito.
Eles também podem falhar . Na função superior, se for encontrado um nome incorreto, passo $1
para nulo $2
e deixo $1
nulo, porque a próxima coisa que faço é ter return
êxito se todos os argumentos tiverem sido processados e o loop chegar ao fim ou, se o argumento for inválido, o shell será expanda o $2
into $1:?
que matará um shell com script e retornará uma interrupção para um interativo enquanto escreve word
para stderr.
No segundo getopts
, as atribuições. E não atribuirá um nome incorreto - em vez disso, escreva; ele escreverá uma mensagem de erro padrão para o stderr. Além disso, ele salva o valor do argumento $OPTARG
se o argumento era o nome de uma variável definida em primeiro lugar. Então, depois de fazer getopts
tudo o que é necessário, é a expansão de eval
um conjunto OPTARG
para a atribuição apropriada.
mktemp
se que é suficiente portátil, e Desativar o valor ea origem do arquivo temporário para atribuir a variável. Pelo menos um arquivo temporário pode ser criado com um nome mais ou menos arbitrário, em contraste com uma variável do shell.