La tubería asigna variable

19

Para simplificar, me gustaría hacer:

echo cart | assign spo;
echo $spo  

Salida: carro

¿Existe tal assignaplicación?

Soy consciente de todas las formas de hacer esto usando la sustitución.

MagoProspero
fuente
¿Por qué quieres hacer esto sin sustitución?
Thanatos
Me gusta el flujo de notación polaca inversa cuando escribo solo con pipas. Estoy codificando mucho más rápido y la calidad / velocidad de los códigos no es tan importante. También yo no Cuando se encadenan es hella más fácil para comentar partes de la cadena y el eco de la salida de corriente en lugar de borrar las garrapatas, etc
MageProspero
Si le preocupa la facilidad de depuración, considere colocar el comando backticks en una serie de líneas separadas. A=$( some | command | here )con cada uno de some |, command |y hereen su propia línea.
roaima

Respuestas:

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

Funcionaría (almacenar la salida de echosin el carácter de nueva línea final en la spovariable) siempre que echosolo salga una línea.

Siempre puedes hacer:

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

Las siguientes soluciones funcionarían en bashscripts, pero no en el bashindicador:

shopt -s lastpipe
echo cat | assign spo

O:

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

Para almacenar la salida de whateverhasta los primeros caracteres NUL (las bashvariables no pueden almacenar caracteres NUL de todos modos) en $spo.

O:

shopt -s lastpipe
whatever | readarray -t spo

para almacenar la salida de whateveren la $spo matriz (una línea por elemento de matriz).

Stéphane Chazelas
fuente
1
¿No debería haber un espacio entre IFS=y read?
caesarsol
Todos granizan la última pipa. También se necesita un conjunto de notas al margen + m (ermmm o -m) desde una línea de comando, ya que la última tubería no funciona con el control de trabajo activo.
MageProspero
17

Podría hacer algo como esto, si usa bash:

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

Desafortunadamente, la variable "spo" no existirá fuera del ciclo while-do-done. Si puede hacer lo que quiere dentro del ciclo while, eso funcionará.

En realidad, puede hacer casi exactamente lo que escribió anteriormente en ATT ksh (no en pdksh o mksh) o en el fabuloso zsh:

% echo cart | read spo
% echo $spo
cart

Entonces, otra solución sería usar ksh o zsh.

Bruce Ediger
fuente
1
Puede usar coprocesos en Korn Shell (por ejemplo mksh): echo cart |& while read -p spo; do echo $spo; done( while IFS= read -p -r spo; do…aunque en realidad es mejor usarlo )
mirabilos
2

Si entiendo el problema correctamente, desea canalizar stdout a una variable. Al menos eso era lo que estaba buscando y terminé aquí. Entonces, para aquellos que comparten mi destino:

spa=$(echo cart)

Asigna carta la variable $spa.

zack-vii
fuente
2
Eso es lo que llaman sustitución, que el OP quería evitar.
Dmitry Grigoryev
Esto fue útil para mí, solo necesitaba asignarlo a una variable, ¡no me importaba cómo llegó allí!
Chris Marisic
1

Si solo desea generar el flujo de tubería actual, use cat.

echo cart | cat 

Si desea continuar su cadena de comandos, intente usar el teecomando para hacer eco de la salida.

echo cart | tee /dev/tty | xargs ls

Puede usar un alias para acortar el comando.

alias tout='tee /dev/tty'
echo cart | tout | xargs ls
BillThor
fuente
¿Por qué querrías canalizar la salida a un plano cat?
roaima
1
@roaima Algunos comandos reconocen que se están ejecutando en un terminal y se comportan de manera diferente que si se están enviando a una tubería. En particular, pueden truncar líneas al ancho de pantalla actual. Para la mayoría de los comandos, el comando cat es redundante.
BillThor
Ah ok, ahora veo lo que intentabas ilustrar. La echo | catconstrucción me arrojó.
roaima
1

Aquí está mi solución al 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
fuente