假设我有一个 10MB 的文本文件foo.txt
,其中有 100,000 行。现在,我想foo.txt
逐个窗口进行处理,窗口大小为 10。
我当前的脚本是这样的:
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}'
但是运行速度很慢,有没有什么简单又高效的办法呢?
答案1
你可以这样做split
:
以下是如何使用它的示例:
split -l 10 input_file output_file_prefix_
该-l
选项代表--lines=
这将分成input_file
每 10 行的块,存放到以下文件中:
output_file_prefix_aa
output_file_prefix_ab
output_file_prefix_ac
...
等等。
有关其他使用方法split
,请参阅man split
或这里
答案2
最好能多介绍一些关于您最终目标的背景信息,而不是代码片段。特别是,您是否可以控制 accuracy.sh?
无论如何,如果你想继续使用 bash,那么你可以这样做
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
答案3
不确定为什么这个从 StackOverflow 迁移过来。虽然split
是超级用户式的答案,问题是关于编程的。例如,这里有一个答案,它实现了你在 中寻找的内容awk
。
真正方便的方面之一awk
是它处理管道的方式。
#!/usr/bin/awk -f
BEGIN {
cmd="/path/to/handler"
}
{
print | cmd
}
NR % 10 == 0 {
close(cmd)
}
如果关闭了,您cmd
将重新打开...并且每 10 行关闭一次,然后重新打开下一行输出。
效果是handler
每输入 10 行运行一次。在文件末尾,handler
将运行剩下的所有行,并cmd
在 awk 退出时自动关闭。
严格来说,您不需要使用类似的变量cmd
来存储命令......但它确实使调整命令变得更简单,因为否则您需要非常仔细地观察命令中的拼写错误close()
。
答案4
此解决方案不使用任何临时文件。它所做的是将每一行存储在可容纳十行的缓冲区数组中。每当行号能被十整除时,它就会打印缓冲区中的所有行。
明显的缺陷是当输入文件(# 行)不能被 10 整除时。解决方案是在 END{} 子句中进行检查。例如:
$回显{1..33} | tr \ \\n |\ awk '{lines=NR} END{ if (lines%10!=0) { print "剩余行"} }' 剩余的线 # STEP1 使用模数对每十分之一做某事 $ echo {1..200} |tr \ \\n|\ awk'{a[NR%10]=$0; if (NR%10==0) {print "ten"}}' | cat -n 1 十 2 十 3 十 四 十 五 十 六 十 七 十 八 十 九 十 10 十 十一 十 十二 十 十三 十 十四 十 十五 十 十六 十 十七 十 十八 十 十九 十 二十 十 # 步骤 2 对每一行进行一些操作 $ echo {1..10} | tr \ \\n | awk'{b+=$0} END {print b}' 55 # 把它放在一起 $ cat every10.awk { a[NR%10]=$0; 如果(NR%10 == 0){ 对于(i 在 a 中){ printf "%s +", a [i] b+=a[i]; } 打印“0=”b; b=0 } } $ echo {1..200} | tr \ \\n | awk -f every10.awk | 列 -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+0355 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
这里的想法是使用 awk 打印十行块并处理它,或者如果操作是简单的算术或字符串操作,则直接使用 awk 处理。