Estoy buscando un comando que acepte (como entrada) varias líneas de texto, cada línea que contenga un solo entero, y genere la suma de estos enteros.
Como fondo, tengo un archivo de registro que incluye mediciones de tiempo. A través del grepping para las líneas relevantes y un poco de sed
formateo, puedo enumerar todos los tiempos en ese archivo. Me gustaría calcular el total. Puedo canalizar esta salida intermedia a cualquier comando para hacer la suma final. Siempre lo he usado expr
en el pasado, pero a menos que se ejecute en modo RPN, no creo que vaya a hacer frente a esto (e incluso entonces sería complicado).
¿Cómo puedo obtener la suma de enteros?
Respuestas:
¿Un poco de awk debería hacerlo?
Nota: algunas versiones de awk tienen comportamientos extraños si va a agregar algo que exceda 2 ^ 31 (2147483647). Ver comentarios para más antecedentes. Una sugerencia es usar en
printf
lugar deprint
:fuente
ls $@ | xargs -i pdftk {} dump_data | grep NumberOfPages | awk '{s+=$2} END {print s}'
awk '{s+=$1} END {printf "%.0f", s}' mydatafile
lugar.Pegar normalmente combina líneas de varios archivos, pero también se puede usar para convertir líneas individuales de un archivo en una sola línea. El indicador delimitador le permite pasar una ecuación de tipo x + x a bc.
Alternativamente, al conectar desde stdin,
fuente
paste
puede usar un guión-
como nombre de archivo, lo que le permitirá canalizar los números de la salida de un comando a la salida estándar de pegar sin la necesidad de crear primero un archivo:<commands> | paste -sd+ - | bc
-
. (Es útil si desea combinar un archivo con stdin).La versión de una línea en Python:
fuente
python -c"import sys; print(sum(map(int, sys.stdin)))"
find . -name '*.epub' -exec stat -c %s '{}' \; | python -c "import sys; nums = [int(n) for n in sys.stdin if int(n) < 10000000]; print(sum(nums)/len(nums))"
import sys; print(sum(int(''.join(c for c in l if c.isdigit())) for l in sys.stdin))
Pondría una gran ADVERTENCIA en la solución comúnmente aprobada:
eso es porque en esta forma awk usa una representación entera con signo de 32 bits: se desbordará para sumas que excedan 2147483647 (es decir, 2 ^ 31).
Una respuesta más general (para sumar enteros) sería:
fuente
echo -e "2147483647 \n 100" |awk '{s+=$1}END{print s}'
muestra2147483747
echo 999999999999999999 | awk '{s+=$1} END {printf "%.0f\n", s}'
produce1000000000000000000
Golpe llano:
fuente
num
define? Creo que de alguna manera está conectado a la< numbers.txt
expresión, pero no está claro cómo.Tenga en cuenta que los números negativos con el prefijo menos deben traducirse
dc
, ya que utiliza_
prefijo en lugar de-
prefijo para eso. Por ejemplo, víatr '-' '_' | dc -f- -e '...'
.Editar: Dado que esta respuesta obtuvo tantos votos "por oscuridad", aquí hay una explicación detallada:
La expresión
[+z1<r]srz1<rp
hace lo siguiente :Como seudocódigo:
Para comprender realmente la simplicidad y el poder de
dc
, aquí hay un script de Python en funcionamiento que implementa algunos de los comandosdc
y ejecuta una versión de Python del comando anterior:fuente
(echo "0"; sed 's/$/ +/' inp; echo 'pq')|dc
.dc -e '0 0 [+?z1<m]dsmxp'
. Por lo tanto, no guardamos todos los números en la pila antes de procesarlos, sino que los leemos y procesamos uno por uno (para ser más precisos, línea por línea, ya que una línea puede contener varios números). Tenga en cuenta que la línea vacía puede terminar una secuencia de entrada.sed
sustitución se puede eliminar, ya quedc
no le importan los espacios entre argumentos y operadores.(echo "0"; sed 's/$/+/' inputFile; echo 'pq')|dc
Con jq :
fuente
Golpe puro y corto.
fuente
f=$(<numbers.txt)
.f=$(cat); echo $(( ${f//$'\n'/+} ))
un script, puede canalizar cualquier cosa a ese script o invocarlo sin argumentos para la entrada stdin interactiva (terminar con Control-D).<numbers.txt
es una mejora, pero, en general, esta solución solo es eficiente para archivos de entrada pequeños; por ejemplo, con un archivo de 1,000 líneas de entrada, laawk
solución aceptada es aproximadamente 20 veces más rápida en mi máquina, y también consume menos memoria, porque el archivo no se lee todo de una vez.fuente
Mis quince centavos:
Ejemplo:
fuente
grep -v '^$'
. ¡Gracias!He hecho un punto de referencia rápido sobre las respuestas existentes que
lua
orocket
),Siempre agregué los números de 1 a 100 millones que era factible en mi máquina en menos de un minuto para varias soluciones.
Aquí están los resultados:
Pitón
Awk
Pasta y Bc
Esto se quedó sin memoria en mi máquina. Funcionó por la mitad del tamaño de la entrada (50 millones de números):
Entonces supongo que habría tomado ~ 35s para los 100 millones de números.
Perl
Rubí
C
Solo por el bien de la comparación, compilé la versión C y probé esto también, solo para tener una idea de cuánto más lentas son las soluciones basadas en herramientas.
Conclusión
C es, por supuesto, el más rápido con 8s, pero la solución Pypy solo agrega una sobrecarga muy pequeña de aproximadamente 30% a 11s . Pero, para ser justos, Pypy no es exactamente estándar. La mayoría de las personas solo tienen instalado CPython, que es significativamente más lento (22 s), exactamente tan rápido como la popular solución Awk.
La solución más rápida basada en herramientas estándar es Perl (15s).
fuente
paste
+bc
era justo lo que estaba buscando para sumar valores hexadecimales, ¡gracias!use std::io::{self, BufRead}; fn main() { let stdin = io::stdin(); let mut sum: i64 = 0; for line in stdin.lock().lines() { sum += line.unwrap().parse::<i64>().unwrap(); } println!("{}", sum); }
Plain bash one liner
fuente
echo $(( $( tr "\n" "+" < /tmp/test) 0 ))
tr
no es exactamente "simple Bash" / nitpickSolución BASH, si desea hacer esto un comando (por ejemplo, si necesita hacer esto con frecuencia):
Entonces uso:
fuente
Creo que AWK es lo que estás buscando:
Puede usar este comando ya sea pasando la lista de números a través de la entrada estándar o pasando el archivo que contiene los números como parámetro.
fuente
Lo siguiente funciona en bash:
fuente
cat numbers.txt
paso sería problemático.Puede usar num-utils, aunque puede ser excesivo para lo que necesita. Este es un conjunto de programas para manipular números en el shell, y puede hacer varias cosas ingeniosas, incluso, por supuesto, sumarlas. Está un poco desactualizado, pero aún funcionan y pueden ser útiles si necesita hacer algo más.
http://suso.suso.org/programs/num-utils/
fuente
numsum numbers.txt
.Me doy cuenta de que esta es una vieja pregunta, pero me gusta esta solución lo suficiente como para compartirla.
Si hay interés, explicaré cómo funciona.
fuente
Golpe puro y de una sola línea :-)
fuente
((
paréntesis))
?$(< numbers.txt)
fuente
Perl puro alternativo, bastante legible, no se requieren paquetes u opciones:
fuente
Para los amantes del rubí
fuente
No puedo evitar enviar esto:
Se encuentra aquí: ¿
La línea elegante de caparazón Unix más elegante para sumar la lista de números de precisión arbitraria?
Y aquí están sus ventajas especiales sobre awk, bc y amigos:
fuente
Usando la utilidad GNU
datamash
:Salida:
Si los datos de entrada son irregulares, con espacios y pestañas en lugares impares, esto puede confundir
datamash
, entonces use el-W
interruptor:... o use
tr
para limpiar el espacio en blanco:fuente
Mi version:
fuente
seq -s+ -5 10 | bc
Puedes hacerlo en python, si te sientes cómodo:
No probado, solo escrito:
Sebastian señaló un guión de una línea:
fuente
cat
se utiliza para demostrar que el script funciona tanto para stdin como para archivos en argv [] (comowhile(<>)
en Perl). Si su entrada está en un archivo, entonces '<' es innecesario.< numbers.txt
demuestra que funciona en stdin tan bien como locat numbers.txt |
hace. Y no enseña malos hábitos.O bien, puede escribir los números en la línea de comando:
Sin embargo, este extrae el archivo, por lo que no es una buena idea usarlo en archivos grandes. Vea la respuesta de j_random_hacker que evita sorber.
fuente
Lo siguiente debería funcionar (suponiendo que su número sea el segundo campo en cada línea).
fuente
One-liner en raqueta:
fuente
C (no simplificado)
fuente
Disculpas de antemano por la legibilidad de los backticks ("` "), pero estos funcionan en shells que no sean bash y, por lo tanto, son más pegajosos. Si usa un shell que lo acepta, el formato $ (comando ...) es mucho más legible (y, por lo tanto, depurable) que 'comando ...', así que siéntase libre de modificarlo por su cordura.
Tengo una función simple en mi bashrc que usará awk para calcular una cantidad de elementos matemáticos simples
Esto hará +, -, *, /, ^,%, sqrt, sin, cos, paréntesis ... (y más, dependiendo de su versión de awk) ... incluso podría imaginarse con printf y formatear el punto flotante salida, pero esto es todo lo que normalmente necesito
para esta pregunta en particular, simplemente haría esto para cada línea:
entonces el bloque de código para sumar cada línea se vería así:
Eso si quisieras sumar solo línea por línea. Sin embargo, para un total de cada número en el archivo de datos
por cierto, si necesito hacer algo rápido en el escritorio, uso esto:
fuente
$()
?