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.