文件頭尾不同條件行的平均值
編輯:為清晰起見對其進行了編輯,並使範例文件最小化且更具可重複性,以便於幫助。謝謝!
我有超過 1000 行的文件。每個文件都使用相同數量的行進行格式化。的格式有 3 個“標題行”,1000+ 行值(正負數,後有 6 個小數位),然後是 13 個“尾行”。行的格式可以在下面看到。在我的真實文件中,在某些行上,我想要不同的命令,例如從行中列印文本,對實際數據取平均值,複製文本的行和數據的平均值以及日期和時間的平均值。
這是一個大綱或各種長文件,其中包含關於每行目標的一些註釋。
下面的大綱是一個 dbriavated 範例。包含數據的行(範例中的第 4-9 行)實際上是真實文件中的第 4-1436 行。那麼大綱中的第 10 行就是實際文件中的第 1437 行。(希望這是有道理的)。數據線可以包含負數或正數,範圍從 -100 到 +5000。
ABCDEFGH # Line 1... print text into output file (same on across all files) 1 # Line 2... Take average of values across all the files in this line 2048 # Line 3... Take average of values across all the files in this line 8.123456 # Line 4... Take average of values across all the files in this line (could be positive or negative) 5.123456 # Line 5... Take average of values across all the files in this line (could be positive or negative) 5.654321 # Line 6... Take average of values across all the files in this line (could be positive or negative) 4.654321 # Line 7... Take average of values across all the files in this line (could be positive or negative) 9.654321 # Line 8... Take average of values across all the files in this line (could be positive or negative) 1.654321 # Line 9... Take average of values across all the files in this line (could be positive or negative) 90.00 # Line 10... Check and make sure value in this line across print if same Sprite # Line 11... check and see if text is same across all values and print if same cats10 # Line 12... check and see if text is same across all values and print if same 07/02/20 # Line 13... See below for explantion on next 3 lines 08:32 # Line 14... 08:32 # Line 15... 290.000000 # Line 16... average across all files on this line 10.750000 # Line 17... average across all files on this line SCANS23 # Line 18... output should be SCANS "average of values" INT_TIME57500 # Line 19... output should be INT_TIME "sum of values" SITE northpole # Line 20...Check if all lines are same if so print line LONGITUDE -147.850037 # Line 21... Output should be LONGITUDE "average" LATITUDE 64.859375 # Line 22... Output should be LONGITUDE "average"
第 13 行是數據的來源日期,第 14 行是開始時間和結束時間。可能使用某種日期到十進制命令..有沒有辦法取日期的平均值?如果一個數據是在 2020 年 7 月 2 日獲取的,而另一個數據是在 2018 年 7 月 2 日獲取的,那麼輸出可以是 19 年 7 月 2 日嗎?時間的平均值也會被考慮在內。
我認為一些擴展的三元運算符可能是一條路徑,但是使用這麼多不同的情況根本不起作用。
awk -F: ' FNR==1 { c++ }; /^LATITUDE/ { a[FNR] += $6 }; /^LONGITUDE/ { a[FNR] += $5 }; /^SITE/ { a[FNR] += $4 }; /^INT_TIME/ { a[FNR] += $3 }; /^SCANS/ { a[FNR] += $2 }; /^[+-]?([0-9]*[.])?[0-9]+$/ { a[FNR] += $1 }; END { for (i in a) { printf (i==22 ? "LATITUDE%f": i==21 ? "LONGITUDE%2.3f": i==20 ? "SITE%2.3f": i==19 ? "INT_TIME%2.3f": i==18 ? "SCANS%2.3f": "%f") "\n", a[i] / c } }' /home/test/test1.* > /home/average
假定所有範例文件都在其中,
/home/test/aaaaaa-bbbb-cc10dddd-L1-2020070119*-01.std
並希望“平均”文件輸出/home/dir/aaaaaa-bbbb-cc10dddd-L1-2020070119-01.std
格式為 /aaaaaa-bbbb-cc10-dddd-L1-“year"“month"“day"“hour”-“elevation number “.std輸入文件於 2020 年 1 月 7 日 19 小時在海拔 1 處拍攝:
/home/dir/dir2/aaaaaa-bbbb-cc10dddd-L1-202007011918-01.std /home/dir/dir2/aaaaaa-bbbb-cc10dddd-L1-202007011929-01.std /home/dir/dir2/aaaaaa-bbbb-cc10dddd-L1-202007011941-01.std /home/dir/dir2/aaaaaa-bbbb-cc10dddd-L1-202007011953-01.std
輸出文件將是
/home/dir/aaaaaa-bbbb-cc10dddd-L1-2020070119-01.std
/home/dir/dir2/aaaaaa-bbbb-cc10dddd-L1-202007011918-01.std
ABCDEFGH 1 2048 -3.249389 -4.544701 5.822962 2.372011 -17.937092 20.000408 5.00 Sprite cats10 07/01/20 19:18 19:18 290.000000 10.690000 SCANS23 INT_TIME57500 SITE northpole LONGITUDE -147.850037 LATITUDE 64.859375
/home/dir/dir2/aaaaaa-bbbb-cc10dddd-L1-202007011929-01.std
ABCDEFGH 1 2048 -6.369022 -4.957337 -2.715081 1.766033 -20.002853 21.522350 5.00 Avantes buoy10 07/01/20 19:29 19:29 290.000000 10.310000 SCANS23 INT_TIME57500 SITE giroof LONGITUDE -147.850037 LATITUDE 64.859375
/home/dir/dir2/aaaaaa-bbbb-cc10dddd-L1-202007011926-01.std
ABCDEFGH 1 2048 2.961413 -14.236549 19.784035 2.711583 -18.305300 9.369226 5.00 Avantes buoy10 07/02/20 19:26 19:26 290.000000 10.310000 SCANS23 INT_TIME57500 SITE giroof LONGITUDE -147.850037 LATITUDE 64.859375
這可能接近您需要的,將
paste
(希望不是太多)輸入文件放入awk
,關閉任何locale
影響:paste file[1-3] | LC_ALL=C awk -v"LNCT=$(wc -l <file1)" ' function avg( sum) {for (i=1; i<=NF; i++) sum += $i return sum/NF } function same() {for (i=2; i<=NF; i++) if ($1 != $i) return 0 return 1 } NR == 1 {print $1 next } NR <= (LNCT-13) || NR >= (LNCT-6) && NR <= (LNCT-5) {print avg() next } NR > (LNCT-13) && NR <= (LNCT-10) {print (same()?$1:"") } NR >= (LNCT-9) && NR <= (LNCT-7) {if (NR == (LNCT-9)) FMT = "%m/%d/%y" else FMT = "%H:%M" for (i=1; i<=NF; i++) {CMD = "date +%s -d\"" $i"\"" CMD | getline $i close (CMD) } CMD = "date +" FMT " -d\"@" avg() "\"" CMD | getline ITEM close (CMD) print ITEM } {ITEM = $1 gsub (/[0-9]*/, "", ITEM) if (gsub (/SCANS|INT_TIME|LONGITUDE|LATITUDE/, "")) {print ITEM, avg() } if (gsub (/SITE/, "")) print ITEM, (same()?$1:"") } ' ABCDEFGH 1 2048 -2.219 -7.91286 7.63064 2.28321 -18.7484 16.964 5.00 07/01/20 19:24 19:24 290 10.4367 SCANS 23 INT_TIME 57500 SITE LONGITUDE -147.85 LATITUDE 64.8594
這有點笨拙,因為它通過行號檢測“特殊處理”行,尤其是。日期/時間,但它似乎做了所要求的。我們需要預先計算行數並通過變數傳遞
wc - l
輸出,awk
假設所有文件都具有相同的長度。可能還有其他/更好的方法。對於日期/時間計算:對於每次發生的事件都執行一個外部命令,這非常耗費資源date
,最重要的是,並非在所有作業系統版本上都可用。它適用於我的 linux 系統,但我願意接受更好的想法。