Como o set
do FreeBSD sh
é gerado em um formato que é adequado para a reinicialização do shell, você pode fazer:
out() case $1 in (_myvar_*) printf '%s\n' "${1%%=*}"; esac
eval "$(set | sed 's/^/out /')"
Isso é o prefixo de cada linha da saída de set
com "out "
e tem isso avaliado como código de shell (onde out
é uma função que imprime a subseqüência de seu primeiro argumento até o primeiro =
) .
sed
também inseriria "out "
no conteúdo da variável multilinha, mas isso ainda seria incluído no argumento de que nossa função out
recebe e passa do primeiro =
, portanto, na parte em que estamos não exibindo.
Por exemplo, em uma saída set
como:
TERM=xterm
USER=stephane
_myvar_foo='line1
line2
line3'
Estaríamos avaliando:
out TERM=xterm
out USER=stephane
out _myvar_foo='line1
out line2
out line3'
Mas ainda assim, como out
é chamado apenas 3 vezes para essas 3 variáveis.
Para imprimir o nome e o valor da variável:
out() case $1 in (_myvar_*)
eval 'printf "name: \"%s\" value: \"%s\"\n" "${1%%=*}" "${'"${1%%=*}"'}"'
esac
eval "$(set | sed 's/^/out /')"
Note que só gera variáveis , e não outros tipos de parâmetros como $-
, parâmetros posicionais ...
Essa abordagem funciona apenas para implementações sh
, em que set
gera apenas variáveis escalar (não funciona para matrizes ou matrizes associativas ou variáveis compostas, em que out var=(x)
se torna um erro de sintaxe) . Aquelas conchas que possuem outros tipos de variáveis geralmente possuem também melhores recursos de introspecção.
Em zsh
:
typeset -pm '_myvar_*'
ou apenas para os nomes
echo $parameters[(I)_myvar_*]
Em bash
:
v=("${!_myvar_@}"); ((${#v[@]})) && typeset -p -- "${v[@]}"
echo "${!_myvar_@}"