O Bash, desde a versão 4.3, fevereiro de 2014 (?), Possui suporte explícito para variáveis de referência ou referências de nome (namerefs), além de "eval", com o mesmo desempenho benéfico e efeito indireto, o que pode ser mais claro em seus scripts e mais difícil para "esqueça de 'eval' e precise corrigir este erro":
declare [-aAfFgilnrtux] [-p] [name[=value] ...]
typeset [-aAfFgilnrtux] [-p] [name[=value] ...]
Declare variables and/or give them attributes
...
-n Give each name the nameref attribute, making it a name reference
to another variable. That other variable is defined by the value
of name. All references and assignments to name, except for⋅
changing the -n attribute itself, are performed on the variable
referenced by name's value. The -n attribute cannot be applied to
array variables.
...
When used in a function, declare and typeset make each name local,
as with the local command, unless the -g option is supplied...
e também:
PARÂMETROS
Uma variável pode ser atribuída ao atributo nameref usando a opção -n para os comandos internos declare ou local (consulte as descrições de declare e local abaixo) para criar um nameref ou uma referência a outra variável. Isso permite que variáveis sejam manipuladas indiretamente. Sempre que a variável nameref for referenciada ou atribuída, a operação é realmente executada na variável especificada pelo valor da variável nameref. Um nameref é comumente usado nas funções de shell para se referir a uma variável cujo nome é passado como argumento para a função. Por exemplo, se um nome de variável for passado para uma função shell como seu primeiro argumento, executando
declare -n ref=$1
dentro da função cria uma variável nameref ref cujo valor é o nome da variável passado como o primeiro argumento. Referências e designações para ref são tratadas como referências e designações para a variável cujo nome foi passado como $ 1. Se a variável de controle em um loop for tiver o atributo nameref, a lista de palavras poderá ser uma lista de variáveis de shell e uma referência de nome será estabelecida para cada palavra da lista, por sua vez, quando o loop for executado. Variáveis de matriz não podem receber o atributo -n. No entanto, as variáveis nameref podem fazer referência a variáveis de matriz e variáveis de matriz subscritas. Os namerefs podem ser desabilitados usando a opção -n para o embutido desabilitado. Caso contrário, se unset for executado com o nome de uma variável nameref como argumento,
Por exemplo ( EDIT 2 : (obrigado Ron), coloca o nome da variável interna da função (prefixado), para minimizar conflitos de variáveis externas, o que deve finalmente responder adequadamente, a questão levantada nos comentários de Karsten):
# $1 : string; your variable to contain the return value
function return_a_string () {
declare -n ret=$1
local MYLIB_return_a_string_message="The date is "
MYLIB_return_a_string_message+=$(date)
ret=$MYLIB_return_a_string_message
}
e testando este exemplo:
$ return_a_string result; echo $result
The date is 20160817
Observe que o bash "declare" builtin, quando usado em uma função, torna a variável declarada "local" por padrão, e "-n" também pode ser usado com "local".
Prefiro distinguir variáveis "importante declarar" de variáveis "chatas locais", portanto, usar "declarar" e "local" dessa maneira atua como documentação.
EDIT 1 - (Resposta ao comentário abaixo por Karsten) - Não consigo mais adicionar comentários abaixo, mas o comentário de Karsten me fez pensar, então eu fiz o seguinte teste que FUNCIONA MUITO BEM, AFAICT - Karsten se você ler isso, forneça um conjunto exato das etapas de teste na linha de comando, mostrando o problema que você supõe existir, porque essas etapas a seguir funcionam perfeitamente:
$ return_a_string ret; echo $ret
The date is 20170104
(Fiz isso agora, depois de colar a função acima em um termo básico - como você pode ver, o resultado funciona muito bem.)
function funcName {
é a sintaxe legada pré-POSIX herdada do início do ksh (onde havia diferenças semânticas que o bash não honra).funcName() {
, com nofunction
, deve ser usado; consulte wiki.bash-hackers.org/scripting/obsolete