Extrator de argumento com nome muito simples para Bash:
#!/bin/bash
getargs()
{
local out=""
for argname in "$@"; do
out="${out}local $argname=\; shift;"
done
printf "%s" "$out"
}
testfun()
{
eval $(getargs a b c)
printf "a = %s, b = %s, c = %s\n" "$a" "$b" "$c"
}
testfun "$@"
Como queremos que os argumentos sejam variáveis locais no escopo dinâmico da função testfun , getargs não pode ser uma chamada de função. Em vez disso, getargs é um minúsculo compilador que traduz uma especificação de argumento como a b c na sintaxe shell , gerando o código que adicionaríamos manualmente para obter a argumento posicional em variáveis locais.
Por exemplo, a saída de
getargs a b c
é o código-fonte:
local a=$1; shift;local b=$1; shift;local c=$1; shift
quando nós eval , ele faz o que parece. No contexto do chamador, ele obtém os três primeiros argumentos posicionais em a , b e c , deslocando-os da lista de argumentos.
Agora podemos levar isso para o próximo nível e adicionar "sinos e assobios".
Para começar, o código gerado pode verificar que existem exatamente três argumentos e diagnosticar.
Poderíamos suportar argumentos opcionais: getargs a b : c (ou qualquer outro) pode significar que a e b são obrigatórios, mas c é opcional. Também poderíamos suportar argumentos finais: getargs a b : c . d poderia gerar código que obtém os dois primeiros argumentos (que são obrigatórios) nos locais a e b . Então, se um terceiro argumento estiver presente, ele entra em c . Qualquer argumento depois disso entra em d , que é uma matriz Bash.
Vou deixar isso como um exercício.
Pena que o shell não tenha um tempo de expansão de macro. A grande desvantagem disso é que o código é gerado toda vez que a função é chamada, mesmo que seja completamente estática.
Você poderia escrever algum tipo de pré-processador (por exemplo, no Awk) para transformar algum tipo de função sintática do açúcar em código shell regular.