假設我有一個 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 "10"} }' |貓-n 1 十 2 十 3 十 4 十 5 十 6 十 7 十 8 十 9 十 10 十 11 十 12 十 13 十 14 十 15 十 16 十 17 十 18 十 19 十 20 十 # 第 2 步對每一行做一些事情 $ 回顯 {1..10} | tr \ \\n | awk '{ b+=$0} END {print b}' 55 # 把它放在一起 $ 貓 every10.awk { [NR%10]=$0; 如果(NR%10==0){ 對於(a中的i){ printf "%s+", a[i] b+=a[i]; } 列印“0=”b; b=0 } } $ 回顯 {1..200} | tr \ \\n | awk -f every10.awk | awk -f every10.awk | 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+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
這裡的想法是使用 awk 列印十行區塊並處理它,或者如果操作是簡單的算術或字串運算,則直接使用 awk 處理。