No se pueden sumar números recibidos de stdin usando bc

8

Estoy tratando de calcular la entropía promedio de los archivos contenidos en una carpeta usando:

{ echo '('; find . -type f -exec entropy {} \; | \
  grep -Eo '[0-9.]+$' | \
  sed -r 's/$/+/g'; echo '0)/'; 
  find . -type f | wc -l; }  | \
tr -d '\n' | bc -l

entropy siendo un ejecutable que calcula la entropía de Shannon de un archivo, dando salidas de la forma:

$ entropy foo
foo: 5.13232

El comando mencionado se equivoca con:

(standard_in) 1: syntax error

Sin embargo, la salida generada parece no tener problemas:

$ { echo '('; find . -type f -exec entropy {} \; | \
    grep -Eo '[0-9.]+$' | \
    sed -r 's/$/+/g'; echo '0)/'; \
    find . -type f | wc -l; }  | \
  tr -d '\n'
(5.13232+2.479+1.4311+0)/3

Y esto también funciona:

$ echo '(2.1+2.1)/2' | bc -l
2.1

¿Qué hay de malo con el comando mencionado?

usuario2064000
fuente
¿Estás dispuesto a usar awk? Sería sustancialmente más fácil.
Bernhard
2
Solo le falta una línea final final para el bccomando: comparar printf '(5.13232+2.479+1.4311+0)/3' | bc -lcon echo '(5.13232+2.479+1.4311+0)/3' | bc -l. (su tr -d '\n'comando elimina la nueva línea final que bcnecesita).
gniourf_gniourf
3
Una solución fácil es insertar { cat; echo; }entre el try el bc: tr -d '\n' | { cat; echo; } | bc -lo reemplazar la tr -d '\n'parte con:{ tr -d '\n'; echo; }
gniourf_gniourf
3
Use en paste -sd'\0' -lugar de tr -d '\n'para preservar el último carácter de nueva línea. (ver también paste -sd+ -para unir líneas con +).
Stéphane Chazelas

Respuestas:

12

Y esto también funciona: echo '(2.1+2.1)/2' | bc -l

Ah, pero intentaste:

echo '(2.1+2.1)/2' | tr -d '\n' | bc -l
(standard_in) 1: syntax error

El uso echo -nlogrará lo mismo: no hay una nueva línea de terminación, y ese es su problema.

encerrada dorada
fuente
5

bctiene una sintaxis bastante particular. dces menos exigente:

find . -type f -exec entropy \{\} + |
sed 's/.*://;N;N;s/\n[^:]*:/+/g;s/+//;s|$| 3/p|' |
dc

Creo que eso es lo que intentas hacer, pero no estoy totalmente seguro. Una muestra de salida más grande que una sola línea ayudaría.

mikeserv
fuente
2
Se podría utilizar dcpara hacer todo el trabajo también: { find . -type f -exec entropy \{\} | sed 's/.*://' ; echo ' 10k[+]sa[z2!>az2!>b]sbzsclbxlc/p'; } | dc. Lo feo 10k[+]sa[z2!>az2!>b]sbzsclbxlc/pes un montón de basura que le indica dcque calcule el promedio de los números que quedan en la pila (con una escala de 10) :D.
gniourf_gniourf
@gniourf_gniourf: eso es mejor que yo, hombre. Dale una respuesta y borraré la mía.
mikeserv
¡No, el tuyo es genial! Realmente no puedo abogar por esta dcbasura de todos modos, es bueno quedarse en esta área de comentarios.
gniourf_gniourf
1
@gniourf_gniourf, sin embargo, es bastante rápido. Quiero aprender a usarlo mejor. Gracias por el material de estudio ...
mikeserv