Pesquisei e não encontrei uma resposta, peço desculpas antecipadamente se já foi perguntado anteriormente.
Estou usando shell no FreeBSD ( /bin/sh
) e quero despejar para stdout todas as variáveis shell ( não ambiente) começando com _myvar_
. O mais próximo que posso chegar é, set | grep '^_myvar_'
mas isso apenas despeja a primeira linha de variáveis de várias linhas (algumas serão de várias linhas e eu preciso delas por completo), e pode ser propenso a erros em casos de borda patológicos, como uma string contendo " myvar " que acontece com quebra de linha antes dessa parte.
se eu pudesse listar apenas nomes de variáveis (não valores), então eu poderia filtrar dentro de a do...read...while
e obter os valores um de cada vez apenas para vars com nomes correspondentes, mas não consigo encontrar uma maneira de fazer isso. Também não posso filtrar a saída completa, porque não há uma maneira determinística de saber se uma linha de saída contém uma continuação ou uma nova variável, que não tem problemas de caso de borda com strings contendo _myvar_
, =
ou newline (\n)
caracteres, ou possivelmente, à direita espaços. Não quero modificar o ambiente, pois o código está incluído em outro código e o ambiente tem que ser estável para isso.
Não é um problema para a saída/lista incluir quaisquer variáveis de ambiente correspondentes, se isso ajudar (se existir alguma - é extremamente improvável que isso aconteça)
Existe uma maneira de fazer isso?
Como o
set
built-in do FreeBSDsh
sai em um formato adequado para reinserção no shell, você pode fazer:Isso é prefixar cada linha da saída de
set
with"out "
e ter isso avaliado como código shell (ondeout
é uma função que imprime a substring 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 que nossaout
função recebe e passa pelo first=
, então na parte que não estamos exibindo.Por exemplo, em uma
set
saída como:Estaríamos avaliando:
Mas isso ainda é bom, pois
out
é chamado apenas 3 vezes para essas 3 variáveis.Para imprimir o nome e o valor da variável:
Observe que ele apenas gera variáveis , não outros tipos de parâmetros como
$-
, parâmetros posicionais ...Essa abordagem funciona apenas para
sh
implementações em queset
apenas gera variáveis escalares (não funcionará para arrays ou arrays associativos ou variáveis compostas, ondeout var=(x)
se torna um erro de sintaxe). Esses shells que têm outros tipos de variáveis geralmente também têm melhores recursos de introspecção.Em
zsh
:ou apenas para os nomes
Em
bash
:Acabei com a seguinte simplificação da solução @StéphaneChazelas, porque não precisava de mais. Postando abaixo caso ajude alguém. Mas Stéphane encontrou a resposta, esta é apenas uma versão modificada, nada mais.
A
eval
chamada prefixa cada linha, mas devido à forma comoset
gera seus valores, na verdade ela cria um único comandoget_vars VARNAME=VALUE
para cada variável. Avaliar isso executa os comandos. Então, cada vez que é chamado,get_vars
verifica se a variável que é capturada na linha atual corresponde à regex necessária e, em caso afirmativo, remove o"get_vars "
prefixo de qualquer segunda linha e exibe o resultado.