如何更高效地将文件分割成碎片?

如何更高效地将文件分割成碎片?

假设我有一个 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 处理。

相关内容