在多個文件中的特定字元串之後 grep 數字並返回平均值的正則表達式
我想在多個文件中的特定字元串之後返回所有數字的平均值,即
我們有 10 個文件(file1.txt,…,file10.txt)。每個文件都包含
Test1: Avg. length 24.01000, time: 0.579 Test2: Avg. length 22.02000, time: 0.879
用不同的數字。
如果我們有 10 個文件,它可能看起來像
文件1.txt
Test1: Avg. length 24.01000, time: 0.679 Test2: Avg. length 22.01000, time: 0.479
文件2.txt
Test1: Avg. length 27.01000, time: 0.279 Test2: Avg. length 24.01000, time: 0.779
…..
文件10.txt
我想要的輸出是所有文件中 Test1 和 Test2 的長度和時間的平均值:
Mean Test1: Avg. length (file1_Test1_length+...+file10_Test1_lenght)/10, time (file1_Test1_time+...+file_10_Test1_time)/10 Mean Test2: Avg. length (file1_Test2_length+...+file10_Test2_lenght)/10, time (file1_Test2_time+...+file_10_Test2_time)/10
要 grep Test1 的完整輸出,我執行:
egrep -rh 'Test1: Avg. length.*' /home/timo/Documents
我不確定如何僅對數字進行 grep。我試過了
egrep -rhP '(?<=length )\d+' /home/timo/Documents
但我得到一個錯誤
grep: conflicting matchers specified
如果有人可以幫助我,我將非常感激!
使用 GNU
datamash
:$ grep '^Test.*Avg\. length.*time:' file*.txt | tr -d ',' | LC_ALL=C datamash -W -s -g 1 mean 4,6 Test1: 25.51 0.479 Test2: 23.01 0.629
這首先提取您使用顯示的行
grep
。我通過匹配行首的文本Test
,然後是字元串Avg. length
和time:
該行的其他位置來做到這一點。你可能想修改這個表達式(我不知道它是否只匹配我們感興趣的行)。然後我從數據中刪除所有逗號,因為它們混淆了對數字的解釋。我用
tr
.
grep
+tr
位也可以用sed
assed '/^Test.*Avg\. length.*time:/!d; s/,//g' file*.txt
然後我使用 GNU
datamash
計算每個測試的平均長度和時間。我首先告訴datamash
大家,空格將用作分隔符,使用-W
. 對-s
數據進行排序,因為它未從grep
+tr
(或sed
)排序,以有效地對數據進行全域分組。分組是通過將每行上的標籤
-g 1
定義為分組鍵來完成的。TestN:
然後,對於每個這樣的組,在第 4 和第 6 列空格分隔的列上計算平均值,其中mean 4,6
.我將語言環境設置為
C
(POSIX 語言環境)datamash
,因為該實用程序可能希望十進制數字使用逗號而不是點作為十進制點。您想稍微裝飾一下輸出嗎,請使用
awk
:sed '/^Test.*Avg\. length.*time:/!d; s/,//g' file*.txt | LC_ALL=C datamash -W -s -g 1 mean 4,6 | awk '{ printf "%s Avg. length: %s time: %s\n", $1,$2,$3 }'
這可能會輸出類似
Test1: Avg. length: 25.51 time: 0.479 Test2: Avg. length: 23.01 time: 0.629
以下
awk
解決方案應該有效:awk -F'[ ,:]+' '$1~/^Test[12]/{l[$1]+=$4; t[$1]+=$6; n[$1]++;} END{if (n["Test1"]) {for (tst in l) printf("Mean %s: Avg. length %f, time: %f\n",tst,l[tst]/n[tst], t[tst]/n[tst]);} else {print "No input found"}}' file*.txt
這將解析輸入文件的起始行
Test1
或Test2
和總和欄位 4 和 6(分別為“長度”和“時間”)。此外,它還會增加數據計數器n
。最後,它將列印平均值(如果找到任何數據)或錯誤消息。如果您確定至少存在一個文件,則可以將其簡化為
awk -F'[ ,:]+' '$1~/^Test[12]/{l[$1]+=$4; t[$1]+=$6; n[$1]++;} END{for (tst in l) printf("Mean %s: Avg. length %f, time: %f\n",tst,l[tst]/n[tst], t[tst]/n[tst]);}' file*.txt
由於您的所有文件似乎都位於單獨的子文件夾中,因此該方法取決於您的 shell。在最簡單的情況下,您可以嘗試
awk -F'[ ,:]+' ' ... ' subdir*/file*.txt