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_@}"