Em bash
, você pode usar ${!varname}
para expandir a variável referenciada pelo conteúdo de outra. Por exemplo:
$ var=hello
$ foo () { echo "${!1}"; }
$ foo var
hello
Da página do manual:
${!prefix*}
${!prefix@}
Names matching prefix. Expands to the names of variables whose names
begin with prefix, separated by the first character of the IFS special
variable. When @ is used and the expansion appears within double quotes,
each variable name expands to a separate word.
Além disso, para definir uma variável referenciada pelo conteúdo (sem os perigos de eval
), você pode usar declare
. Por exemplo:
$ var=target
$ declare "$var=hello"
$ echo "$target"
hello
Assim, você poderia escrever sua função assim (tome cuidado, porque se você usa declare
em uma função, você deve dar -g
ou a variável será local):
shopt -s extglob
assign()
{
target=$1
bigstr=${!1}
substr=$2
if [ -z "$bigstr" ]; then
declare -g -- "$target=$substr"
elif [[ $bigstr != @(|*:)$substr@(|:*) ]]; then
declare -g -- "$target=$bigstr:$substr"
fi
}
E use-o como:
assign PATH /path/to/binaries
Note que eu também corrigi um erro onde se substr
já é uma substring de um dos membros separados por dois pontos de bigstr
, mas não seu próprio membro, então não seria adicionado. Por exemplo, isso permitiria a adição de /bin
a uma variável PATH
contendo /usr/bin
. Ele usa os conjuntos extglob
para corresponder ao início / fim da sequência ou dois-pontos e depois a qualquer outra coisa. Sem extglob
, a alternativa seria:
[[ $bigstr != $substr && $bigstr != *:$substr &&
$bigstr != $substr:* && $bigstr != *:$substr:* ]]