我有一個大 (>10GB) 檔案,它是一個 InfluxDB 線路協議匯出。線路協議格式大致是
measurement,tag1=value1,tag2=value2,... value=XXX timestamp
例如
deconz.0.Sensors.10.pressure value=998 1622621407241000000
deconz.0.Sensors.10.pressure value=999 1622621970836000000
deconz.0.Sensors.10.pressure value=999 1622624177180000000
deconz.0.Sensors.10.pressure value=999 1622625419255000000
deconz.0.Sensors.10.pressure value=998 1622625975843000000
deconz.0.Sensors.11.battery value=85 1622621407241000000
deconz.0.Sensors.11.battery value=88 1622623616070000000
deconz.0.Sensors.11.battery value=88 1622660536826000000
deconz.0.Sensors.11.battery value=85 1622663594301000000
deconz.0.Sensors.11.battery value=88 1622666692089000000
deconz.0.Sensors.11.temperature value=21.44 1622621407241000000
deconz.0.Sensors.11.temperature value=21.61 1622646781032000000
deconz.0.Sensors.11.temperature value=21.64 1622650221200000000
deconz.0.Sensors.12.humidity value=55.54 1622621407242000000
deconz.0.Sensors.12.humidity value=55.7 1622633302339000000
deconz.0.Sensors.12.humidity value=55.73 1622636722283000000
deconz.0.Sensors.12.humidity value=55.89 1622640061715000000
deconz.0.Sensors.12.humidity value=55.96 1622643481822000000
deconz.0.Sensors.13.battery value=85 1622621407242000000
deconz.0.Sensors.13.battery value=85 1622908043752000000
deconz.0.Sensors.13.temperature value=24.01 1622621407242000000
deconz.0.Sensors.13.temperature value=24.13 1622626969228000000
deconz.0.Sensors.13.temperature value=24.21 1622630216027000000
deconz.0.Sensors.13.temperature value=24.33 1622630974954000000
deconz.0.Sensors.14.humidity value=47.72 1622632937200000000
deconz.0.Sensors.14.humidity value=47.8 1622633311833000000
deconz.0.Sensors.14.humidity value=46.7 1622636659393000000
deconz.0.Sensors.15.pressure value=1002 1622673441206000000
deconz.0.Sensors.15.pressure value=1002 1622685777307000000
deconz.0.Sensors.15.pressure value=1003 1622686242842000000
deconz.0.Sensors.16.temperature value=23.47 1622654455194000000
deconz.0.Sensors.16.temperature value=23.55 1622655939005000000
deconz.0.Sensors.16.temperature value=23.57 1622655959670000000
energymeter_total,uuid=c4695262-624c-11ea-b2f7-374e5ccddc43 value=30436.6 1622594844107000000
energymeter_total,uuid=c4695262-624c-11ea-b2f7-374e5ccddc43 value=30436.6 1622594908800000000
energymeter_total,uuid=c4695262-624c-11ea-b2f7-374e5ccddc43 value=30436.6 1622594973493000000
energymeter_total,uuid=c4695262-624c-11ea-b2f7-374e5ccddc43 value=30436.6 1622595158917000000
energymeter_total,manual=true value=26984.9 1592641140000000000
我想通過測量來分割這個檔案,即。直到第一個逗號或空格,使用測量名稱作為目標檔案名。
這可以完成作業(逗號作為分隔符除外),但速度非常慢(在帶有 SSD 存盤的 Intel i5 上運行 8 小時):
cat ../influx_export | while read FILE VAL TS ; do echo "$FILE $VAL $TS" >> "$FILE" ; done
我確信有一個至少快 10 倍的腳本解決方案(無編譯代碼)。但是,源檔案太大而無法完全放入 RAM。
有沒有使用 awk、perl、sed、ruby 等更有效的方法?
uj5u.com熱心網友回復:
bash
迭代檔案的速度非常慢(因為read
一次只讀取一個字符,以確保它不會在換行符之后消耗任何可能供后續命令讀取的內容)。
改用awk
:
awk -F'[, ]' '{
print $0 >> $1
}' ../influx_export
如果 有很多唯一值$1
,您可能會遇到“打開的檔案過多”錯誤。在這種情況下,一個簡單(如果效率低下)的解決方案是在寫入每個檔案后立即顯式關閉它。即使awk
需要為每一行打開一個檔案,這仍然應該比使用 pure 更快bash
。
awk -F'[, ]' '{
print $0 >> $1; close($1)
}' ../influx_export
uj5u.com熱心網友回復:
不要使用 shell 回圈來操作文本,請參閱why-is-using-a-shell-loop-to-process-text-considered-bad-practice。
如果不完全正確,使用DSU方法可能會接近您想要的:
awk -F'[, ]' '{print $1, NR, $(NF-1), $NF}' file |
sort -k1,1 -k2,2n |
awk '
$1 != out {
close(out)
out = $1
}
{ print $3, $4 > out }
'
但它顯然未經測驗,因為您沒有提供我們可以測驗的樣本輸入和預期輸出。
每個awk
命令一次只處理 1 行,因此幾乎不使用記憶體,并且該sort
命令旨在通過使用需求分頁等來處理大檔案,因此它不需要將整個輸入放入 RAM 中,所以上面應該有有效地處理您的輸入檔案沒有問題。
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/496504.html
上一篇:在Bash命令上使用sed