Eu tenho a seguinte função recursiva para definir variáveis de ambiente:
function par_set {
PAR=$1
VAL=$2
if [ "" != "$1" ]
then
export ${PAR}=${VAL}
echo ${PAR}=${VAL}
shift
shift
par_set $*
fi
}
Se eu chamá-lo por si só, ele define a variável e ecoa para stdout:
$ par_set FN WORKS
FN=WORKS
$ echo "FN = "$FN
FN = WORKS
Redirecionar stdout para um arquivo também funciona:
$ par_set REDIR WORKS > out
cat out
REDIR=WORKS
$ echo "REDIR = "$REDIR
REDIR = WORKS
Mas, se eu canalizar stdout para outro comando, a variável não será definida:
$ par_set PIPE FAILS |sed -e's/FAILS/BARFS/'
PIPE=BARFS
$ echo "PIPE = "$PIPE
PIPE =
Por que o pipe impede que a função exporte a variável? Existe uma maneira de corrigir isso sem recorrer a arquivos temporários ou pipes nomeados?
Resolvido:
Código de trabalho graças a Gilles:
par_set $(echo $*|tr '=' ' ') > >(sed -e's/^/ /' >> ${LOG})
Isso permite que o script seja chamado assim:
$ . ./script.sh PROCESS_SUB ROCKS PIPELINES=NOGOOD
$ echo $PROCESS_SUB
ROCKS
$ echo $PIPELINES
NOGOOD
$ cat log
7:20140606155622162731431:script.sh:29581:Parse Command Line parameters. Params must be in matched pairs separated by one or more '=' or ' '.
PROCESS_SUB=ROCKS
PIPELINES=NOGOOD
Projeto hospedado no bitbucket https://bitbucket.org/adalby/monitor-bash se estiver interessado em código completo.
Isso não funciona porque cada lado do pipe é executado em um subshell
bash
e as variáveis definidas em um subshell são locais para esse subshell.Atualizar:
Parece fácil passar variáveis do pai para o shell filho, mas é muito difícil fazê-lo da outra maneira. Algumas soluções alternativas são denominadas pipes, arquivos temporários, gravação em stdout e leitura no pai, etc.
Algumas referências:
http://mywiki.wooledge.org/BashFAQ/024
/programming//q/15541321/3565972
/programming//a/15383353/3565972
http://forums.opensuse.org/showthread .php / 458979-Como-exportar-variável-no-subshell-back-out-to-parent
fonte
$$
é o mesmo para os pais e filhos. Você pode usar$BASHPID
para obter o pid subshell. Quando euecho $$ $BASHPID
dentropar_set
eu recebo diferentes pids.Você aponta os subshells - que podem ser contornados com alguns detalhes no shell do lado de fora de um pipeline - mas a parte mais difícil do problema tem a ver com a simultaneidade do pipeline .
Todos os membros do processo do pipeline são iniciados de uma só vez e, portanto, o problema pode ser mais fácil de entender se você olhar assim:
Os processos de pipeline não podem herdar os valores da variável porque eles já estão desativados e em execução antes que a variável seja definida.
Eu realmente não consigo entender qual é o objetivo da sua função - a que finalidade ela serve e que
export
ainda não serve ? Ou apenasvar=val
? Por exemplo, aqui está quase o mesmo pipeline novamente:E com
export
:Assim, sua coisa pode funcionar como:
O qual registraria a
sed
saída de um arquivo e entregaria à sua função como uma divisão de shell"$@"
.Ou alternativamente:
Se eu fosse escrever sua função, provavelmente ficaria assim:
fonte
|pipeline | sh
sh
. Ele já está usandoexport
.