Pipe atribui variável

19

Para simplificar, eu gostaria de fazer:

echo cart | assign spo;
echo $spo  

Saída: carrinho

Existe um assignaplicativo assim?

Estou ciente de todas as maneiras de fazer isso usando a substituição.

MageProspero
fonte
Por que você quer fazer isso sem substituição?
Thanatos
Eu gosto do fluxo de notação polonês reverso ao escrever apenas com tubos. Eu sou uma codificação muito mais rápida e a qualidade / velocidade dos códigos não é tão importante. Também eu não quando o encadeamento é hella mais fácil para comentar as partes da cadeia e ecoar a saída de corrente em vez de apagar carrapatos etc.
MageProspero
Se você estiver preocupado com a facilidade de depuração, considere colocar o comando backticks em uma série de linhas separadas. A=$( some | command | here )com cada um de some |, command |e hereem sua própria linha.
roaima

Respostas:

11
echo cart | { IFS= read -r spo; printf '%s\n' "$spo"; }

Funcionaria (armazenaria a saída echosem o caractere de nova linha à direita na spovariável) desde que echoemita apenas uma linha.

Você sempre pode fazer:

assign() {
  eval "$1=\$(cat; echo .); $1=\${$1%.}"
}
assign spo < <(echo cart)

As seguintes soluções funcionariam em bashscripts, mas não no bashprompt:

shopt -s lastpipe
echo cat | assign spo

Ou:

shopt -s lastpipe
whatever | IFS= read -rd '' spo

Para armazenar a saída de whateveraté os primeiros caracteres NUL ( bashvariáveis não pode armazenar caracteres NUL de qualquer maneira) no $spo.

Ou:

shopt -s lastpipe
whatever | readarray -t spo

para armazenar a saída de whateverna $spo matriz (uma linha por elemento da matriz).

Stéphane Chazelas
fonte
1
não deveria haver um espaço entre IFS=e read?
caesarsol
Todos saudam o último cachimbo. Também é necessário definir o conjunto de notas laterais + m (ermmm ou -m) a partir de uma linha de comando, pois o último canal não funciona com o controle de trabalho ativo.
precisa saber é o seguinte
17

Você pode fazer algo assim, se você usar bash:

echo cart | while read spo; do echo $spo; done

Infelizmente, a variável "spo" não existirá fora do loop while-do-done. Se você conseguir o que deseja dentro do loop while, isso funcionará.

Na verdade, você pode fazer quase exatamente o que escreveu acima no ATT ksh (não no pdksh ou mksh) ou no fabuloso zsh:

% echo cart | read spo
% echo $spo
cart

Portanto, outra solução seria usar ksh ou zsh.

Bruce Ediger
fonte
1
Você pode usar coprocesses na Shell Korn (por exemplo mksh): echo cart |& while read -p spo; do echo $spo; done(na verdade, melhor usar while IFS= read -p -r spo; do…embora)
mirabilos
2

Se eu entendi o problema corretamente, você deseja canalizar stdout para uma variável. Pelo menos era o que eu estava procurando e acabei aqui. Então, para aqueles que compartilham o meu destino:

spa=$(echo cart)

Atribui cartà variável $spa.

zack-vii
fonte
2
É o que eles chamam de substituição, que o OP queria evitar.
Dmitry Grigoryev
Isso foi útil para mim, eu só precisava atribuí-lo a uma variável, não me importava como chegava lá!
Chris Marisic em 24/04
1

Se você deseja apenas exibir o fluxo atual de tubos, use cat.

echo cart | cat 

Se você deseja continuar sua cadeia de comandos, tente usar o teecomando para ecoar a saída.

echo cart | tee /dev/tty | xargs ls

Você pode usar um alias para encurtar o comando.

alias tout='tee /dev/tty'
echo cart | tout | xargs ls
BillThor
fonte
Por que você gostaria de canalizar a saída para uma planície cat?
roaima
1
@roaima Alguns comandos reconhecem que estão rodando em um terminal e se comportam de maneira diferente do que se estivessem enviando para um tubo. Em particular, eles podem truncar linhas para a largura da tela atual. Para a maioria dos comandos, o comando cat é redundante.
BillThor
Ah, ok, agora vejo o que você estava tentando ilustrar. A echo | catconstrução me jogou.
roaima 27/01
1

Aqui está a minha solução para o problema.

# assign will take last line of stdout and create an environment variable from it
# notes: a.) we avoid functions so that we can write to the current environment
#        b.) aliases don't take arguments, but we write this so that the "argument" appears
#            behind the alias, making it appear as though it is taking one, which in turn
#            becomes an actual argument into the temporary script T2.
# example: echo hello world | assign x && echo %x outputs "hello world"
alias assign="tail -1|tee _T1>/dev/null&&printf \"export \\\$1=\$(cat _T1)\nrm _T*\">_T2&&. _T2"
Brian Kramer
fonte