Suponha que eu tenha um arquivo de texto de 10 MB foo.txt
e 100.000 linhas. Agora, quero processar foo.txt
janela por janela, com janela de tamanho 10.
Meu script atual é assim:
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}'
Mas corre devagar. Existe alguma maneira simples e mais eficiente de fazer isso?
Responder1
Você pode fazer isso com split
:
Aqui está um exemplo de como usá-lo:
split -l 10 input_file output_file_prefix_
A -l
opção significa--lines=
E isso será dividido input_file
em pedaços com 10 linhas cada, nestes arquivos:
output_file_prefix_aa
output_file_prefix_ab
output_file_prefix_ac
...
e assim por diante.
Para outras maneiras que você pode usar split
, veja man split
ouaqui
Responder2
Seria útil ter um pouco mais de contexto quanto ao seu objetivo final, em vez de um trecho de código. Em particular, você tem algum controle sobre o Precision.sh?
De qualquer forma, se você quiser continuar usando o bash, você pode fazer
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
Responder3
Não sei por que isso foi migrado do StackOverflow. Enquanto split
é umsuperusuárioresposta estilo, a pergunta era sobre programação. Por exemplo, aqui está uma resposta que implementa o que você está procurando no awk
.
Um dos aspectos realmente úteis awk
é a maneira como ele lida com tubos.
#!/usr/bin/awk -f
BEGIN {
cmd="/path/to/handler"
}
{
print | cmd
}
NR % 10 == 0 {
close(cmd)
}
Seu cmd
será reaberto se estiver fechado ... e for fechado a cada 10 linhas, para ser reaberto na próxima linha de saída.
O efeito será executado handler
a cada 10 linhas de entrada. No final do arquivo, handler
será executado com as linhas restantes, pois cmd
é fechado automaticamente quando o awk sai.
Estritamente falando, você não precisa usar uma variável como cmd
para armazenar o comando ... mas torna mais simples ajustar o comando, já que caso contrário você precisaria observar MUITO cuidadosamente se há erros de digitação no seu arquivo close()
.
Responder4
Esta solução não usa arquivos temporários. O que isso faz é armazenar cada linha em uma matriz de buffer que pode conter dez linhas. Cada vez que o número da linha é divisível por dez, ele imprime todas as linhas do buffer.
A armadilha óbvia é quando o arquivo de entrada (# linhas) não é divisível por dez. A solução é fazer verificações em uma cláusula END{}. Algo como:
$ eco {1..33} | tr\\n |\ awk '{linhas=NR} END{ if (linhas%10!=0) { imprimir "linhas restantes"} }' linhas restantes # STEP1 usa módulo para fazer algo a cada décimo $ echo {1..200} |tr \ \\n |\ awk '{a[NR%10]=$0; if (NR%10==0) {print "dez"} }' | gato -n 1 dez 2 dez 3 dez 4 dez 5 dez 6 dez 7 dez 8 dez 9 dez 10 dez 11 dez 12 dez 13 dez 14 dez 15 dez 16 dez 17 dez 18 dez 19 dez 20 dez # PASSO 2 faça algo com cada linha $ eco {1..10} | tr\\n | awk '{b+=$0} END {imprimir b}' 55 # Juntar as peças $ gato a cada 10.awk { a[NR%10]=$0; if (NR%10==0) { para (eu em a) { printf "%s+", a[i] b+=uma[i]; } imprima "0="b; b=0 } } $ eco {1..200} | tr\\n | awk -f cada10.awk | coluna -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
A ideia aqui é usar awk print blocos de dez linhas e processá-los, ou processar diretamente com awk se a operação for simples aritmética ou operações de string.