Supongamos que tengo un archivo de texto de 10 MB foo.txt
y tiene 100.000 líneas. Ahora quiero procesar foo.txt
ventana por ventana, con un tamaño de ventana 10.
Mi script actual es así:
for ((i=0;i<$lines;i=i+$step))
do
head -$((i+step)) $1 | tail -$step > tmp1
head -$((i+step)) $2 | tail -$step > tmp2
setstr=$setstr' '`./accuracy.sh tmp1 tmp2`
done
echo $setstr | awk '{for (i=1;i<=NF;i++) sum+=$i; }END{print sum/NF}'
Pero va lento. ¿Existe alguna forma sencilla y más eficiente de hacer esto?
Respuesta1
Puedes hacer eso con split
:
A continuación se muestra un ejemplo de cómo utilizarlo:
split -l 10 input_file output_file_prefix_
La -l
opción significa--lines=
Y esto se dividirá input_file
en fragmentos de 10 líneas cada uno, en estos archivos:
output_file_prefix_aa
output_file_prefix_ab
output_file_prefix_ac
...
etcétera.
Para conocer otras formas en las que puede utilizar split
, consulte man split
oaquí
Respuesta2
Sería útil tener un poco más de contexto sobre su objetivo final en lugar de un fragmento de código. En particular, ¿tiene algún control sobre precision.sh?
De todos modos, si quieres seguir usando bash, entonces puedes hacer
for ((i=0;i<$lines;i+=$step))
do
let end=i+10
sed -n $i,${end}p $1 >tmp1
sed -n $i,${end}p $2 >tmp2
...
done
Respuesta3
No estoy seguro de por qué se migró desde StackOverflow. mientras split
es unsuperusuarioRespuesta de estilo, la pregunta era sobre programación. Por ejemplo, aquí hay una respuesta que implementa lo que estás buscando en awk
.
Uno de los aspectos realmente útiles awk
es la forma en que maneja las tuberías.
#!/usr/bin/awk -f
BEGIN {
cmd="/path/to/handler"
}
{
print | cmd
}
NR % 10 == 0 {
close(cmd)
}
Se cmd
volverá a abrir si está cerrado... y se cierra cada décima línea, para volver a abrirse en la siguiente línea de salida.
El efecto será ejecutar handler
cada 10 líneas de entrada. Al final del archivo, handler
se ejecutará con las líneas que queden, y cmd
se cerrará automáticamente cuando awk salga.
Estrictamente hablando, no necesita usar una variable como cmd
para almacenar el comando... pero hace que sea más sencillo ajustar el comando, ya que de lo contrario necesitaría observar MUY cuidadosamente para detectar errores tipográficos en su archivo close()
.
Respuesta4
Esta solución no utiliza ningún archivo temporal. Lo que hace es almacenar cada línea en una matriz de búfer que puede contener diez líneas. Cada vez que el número de línea es divisible por diez, imprime todas las líneas en el búfer.
El problema obvio es cuando el archivo de entrada (# líneas) no es divisible por diez. La solución es realizar comprobaciones en una cláusula END{}. Algo como:
$ eco {1..33} | tr\\\n |\ awk '{lines=NR} END{ if (lines%10!=0) { print "líneas sobrantes"} }' líneas sobrantes # PASO 1 usa el módulo para hacer algo cada diez $ eco {1..200} |tr \ \\n |\ awk '{a[NR%10]=$0; if (NR%10==0) {imprimir "diez"} }' | gato -n 1 diez 2 diez 3 diez 4 diez 5 diez 6 diez 7 diez 8 diez 9 diez 10 diez 11 diez 12 diez 13 diez 14 diez 15 diez 16 diez 17 diez 18 diez 19 diez 20 diez # PASO 2 haz algo con cada línea $ eco {1..10} | tr\\\n | awk '{ b+=$0} FIN {imprimir b}' 55 # Poniendo todo junto $ gato cada 10.awk { a[NR%10]=$0; si (NR%10==0) { para (yo en a) { printf "%s+", a[yo] b+=a[i]; } imprimir "0="b; b=0 } } $ eco {1..200} | tr\\\n | awk -f cada10.awk | columna -s= -t 4+5+6+7+8+9+10+1+2+3+0 55 14+15+16+17+18+19+20+11+12+13+0 155 24+25+26+27+28+29+30+21+22+23+0 255 34+35+36+37+38+39+40+31+32+33+0 355 44+45+46+47+48+49+50+41+42+43+0 455 54+55+56+57+58+59+60+51+52+53+0 555 64+65+66+67+68+69+70+61+62+63+0 655 74+75+76+77+78+79+80+71+72+73+0 755 84+85+86+87+88+89+90+81+82+83+0 855 94+95+96+97+98+99+100+91+92+93+0 955 104+105+106+107+108+109+110+101+102+103+0 1055 114+115+116+117+118+119+120+111+112+113+0 1155 124+125+126+127+128+129+130+121+122+123+0 1255 134+135+136+137+138+139+140+131+132+133+0 1355 144+145+146+147+148+149+150+141+142+143+0 1455 154+155+156+157+158+159+160+151+152+153+0 1555 164+165+166+167+168+169+170+161+162+163+0 1655 174+175+176+177+178+179+180+171+172+173+0 1755 184+185+186+187+188+189+190+181+182+183+0 1855 194+195+196+197+198+199+200+191+192+193+0 1955
La idea aquí es utilizar awk imprimir bloques de diez líneas y procesarlos, o procesar con awk directamente si la operación es aritmética simple o operaciones de cadena.