
因此,出於個人和學習經驗的原因,我開始將天氣資料資料庫化。我正在使用 wgrib2 解析數據,並導入到 MySQL。因為數據採用不同的單位格式 - 風“U”和“V”分量、開爾文等...我必須將其轉換為風速節、風度半徑和溫度攝氏度...等。
我建立了一個 bash for 迴圈來循環遍歷所有資料值,但效率相當低,而且我確信有更好的方法可以做到這一點。它依賴awk,很多...,需要15-17分鐘來解析大約1150個站點的數據,每個站點在MySQL資料庫中有一個結構完全相同的表,有160列。
我為 TK(溫度開爾文)、RH(濕度)等設定的 bash 陣列...具有 1000、975、950、925...等一直到 100 毫巴的值。
for thKey in ${!TK[@]}
do
thRH=${RH[$thKey]}
thTK=${TK[$thKey]}
thTC=$(echo -| awk -v tk="$thTK" '{printf "%.1f\n", tk-273.15}')
thWU=${WU[$thKey]}
thWV=${WV[$thKey]}
thTD=$(echo -| awk -v tc="$thTC" -v rh="$thRH" '{printf "%.1f\n", tc-(100-rh)/5}')
thWD=$(echo -| awk -v wu="$thWU" -v wv="$thWV" '{printf "%.0f\n", 57.29578*(atan2(wu, wv))+180}')
thWS=$(echo -| awk -v wu="$thWU" -v wv="$thWV" '{printf "%.1f\n", sqrt(wu*wu+wv*wv)*1.944}')
sed -i '/\/station_id/a <'"$thKey"'T>'"$thTC"'<\/'"$thKey"'T><'"$thKey"'D>'"$thTD"'<\/'"$thKey"'D><'"$thKey"'WD>'"$thWD"'<\/'"$thKey"'WD><'"$thKey"'WS>'"$thWS"'<\/'"$thKey"'WS>' $xmlOut
done
正如你所看到的,明顯的問題是它對awk 進行了大約1150 * 160 次調用...所以可能將主數組傳遞給awk 並且每個循環只生成awk 一次(我現在正在做的事情的1 /160! )會更有效率。但我似乎無法獲得適合這種做法的 awk 語法...
awk --version
GNU Awk 4.1.3,API:1.1(GNU MPFR 3.1.4,GNU MP 6.1.0)
這是一個例子:
TK=(325,350,231,655)
echo -| awk -v tk="${TK[*]}" '{split(tk,tka,/ /)} { for (i=0; i<=NF; i++) { printf "%.1f\n", tka[i]-273.15 } } '
-273.1 51.9
^ 這是不對的。該陣列有 4 個值,它不應該只傳回 2 個。
echo -| awk -v tk="${TK[*]}" '{split(tk,tka,/ /)} { for (i=0; i<=length(tka); i++) { printf "%.1f\n", tka[i]-273.15 } } '
^ 這會產生無限循環。
有任何想法嗎?也許學習一些 Perl 並將所有這些傳遞給 Perl 腳本?
答案1
就我個人而言,是的,我會用 Perl 來完成這一切。 :-)
TK=(325,350,231,655)
哎呀。小心。您已經建立了一個單元素數組,其中以逗號分隔的字串作為元素。
echo -| awk -v tk="${TK[*]}" '{split(tk,tka,/ /)} { for (i=0; i<=NF; i++) { printf "%.1f\n", tka[i]-273.15 } } '
awk
陣列從 1 開始,而不是從零開始。
因為您指派了變量,所以您實際上並沒有將 STDIN 資料用於 NF 值以外的任何內容(但您只傳入了一個元素)。我們不使用 NF,而是明確地計算結果split
。也許是這樣的:
$ TK=(325 350 231 655)
$ echo - | awk -v tk="${TK[*]}" '{fields=split(tk,tka,/ /)} { for (i=1; i<=fields; i++) { printf "%.1f\n", tka[i]-273.15 } } '
51.9
76.9
-42.1
381.9
正如 dave_thompson_085 所提到的,您透過直接將資料分配給變數而不是僅透過 STDIN 發送它來完成額外的工作。更常見的可能是這樣的:
$ echo ${TK[*]} | awk '{for (i=1; i<=NF; i++) { printf "%.1f\n", $i-273.15 } } '
51.9
76.9
-42.1
381.9
如果您確實想要開始解決perl
方案:
$ echo ${TK[*]} | perl -lane 'for $item (@F) {print $item-273.15}'
51.85
76.85
-42.15
381.85