¿Agregar a una tubería y pasar?

¿Agregar a una tubería y pasar?

Tengo una función bash simple que divide dos números:

echo "750/12.5" | bc

Me gustaría tomar el resultado bc, agregarlo /24y canalizar dicho resultado a otra instancia de bc.

Algo como:

echo "750/12.5" | bc | echo $1 + "/24" | bc

¿Dónde $1está el resultado canalizado?

PD: Me doy cuenta de que podría hacer que echo "750/12.5/24" | bcmi pregunta se refiera más a agregar texto al resultado de una canalización.

Respuesta1

Logré esto usando sedy reemplazando el final de la línea:

echo "my text" | sed 's/$/ more text/'

Devoluciones:

my text more text

Tu ejemplo:

echo "750/12.5" | bc | sed 's/$/\/24/' | bc

Respuesta2

Enfoque alternativo:

TL;DR: Úselo catpara concatenar con stdin ( -) como argumento. Tenga en cuenta que separará con una nueva línea sus transmisiones concatenadas; retírelo si no lo desea.

Desafortunadamente, este enfoque es un poco engorroso para su caso de uso particular, ya que bcfalla si hay una nueva línea en medio de esa expresión:

$ echo "750/12.5" | bc | cat - <(echo "/24") | bc
60
(standard_in) 2: parse error

Puede solucionar este problema eliminando la nueva línea del bcresultado original:

$ echo "750/12.5" | bc | tr -d '\n' | cat - <(echo "/24") | bc
2

Sin embargo, encontré esta pregunta buscando en Google "bash append to pipe", y en mi caso, en realidadhacerQuiero esa nueva línea entre las concatenaciones. Entonces, para aquellos que están aquí por la misma razón, usen | cat - <(...):

$ echo foo | cat - <(echo bar)
foo
bar
$ echo foo | cat - <(echo bar) | sort | cat - <(echo last_line)
bar
foo
last_line
$ echo foo | cat - <(echo bar) | sort | cat <(echo header) - <(echo last_line)
header
bar
foo
last_line

Respuesta3

En la opción más simple, esto se agrega al flujo de tubería:

$ echo "750/12.5" | { bc; echo "/24"; }
60
/24

Sin embargo, eso tiene una nueva línea inesperada, para evitar eso necesitas usar tr:

$ echo "750/12.5" | { bc | tr -d '\n' ; echo "/24"; }
60/24

O, dado el hecho de que una expansión de comando elimina las nuevas líneas finales:

$ printf '%s' $( echo "750/12.5" | bc ); echo "/24"
60/24

Pero probablemente, la forma correcta debería ser similar a:

$ echo "$(echo "750/12.5" | bc )/24"
60/24

Lo cual, para ser usado en bc, podría escribirse así:

$ bc <<<"$(bc <<<"750/12.5")/24"
2

Lo cual, para obtener una precisión de número flotante razonable, debería ser algo como:

$ bc <<<"scale=10;$(bc <<<"scale=5;750/12.5")/24"
2.5000000000

Tenga en cuenta la necesidad de dos escalas, ya que hay dos instancias de bc.

Por supuesto, una instancia de bc sólo necesita una escala:

$ bc <<<"scale=5;750/12.5/24"

De hecho, lo que deberías pensar es en términos de una cadena:

$ a=$(echo "750/12.5")        # capture first string.
$ echo "$a/24" | bc           # extend the string
2

El comentario anterior sobre la escala sigue siendo válido aquí.

Respuesta4

Podrías usar awkpara insertar/añadir cualquier cosa a la tubería:

$ date | awk 'BEGIN{print "prefix line"} {print}  END{print "suffix  line"}'
prefix line
Mo 21. Aug 15:24:30 CEST 2023
suffix  line

dónde

  • date- es su canal de entrada (fecha actual, por ejemplo, aquí)
  • BEGIN{print "prefix line"}- este bloque insertará la salida antes de main
  • {print}- imprime el contenido de la tubería de entrada; Uno podría hacer algún procesamiento aquí si es necesario.
  • END{print "suffix line"} - esto agrega la salida después de principal

Para hacer lo mismo en una sola línea, simplemente use printf:

$ date | awk 'BEGIN{printf("prefix line >> ")} {printf($0)}  END{printf(" << suffix  line")}'
prefix line >> Mo 21. Aug 15:32:08 CEST 2023 << suffix  line/upload/sc505enb/tmp>

$ echo "750/12.5" | bc | awk '{printf($0)}  END{printf("/24\n")}'
60/24

información relacionada