複数のファイルから特定の文字列に続くすべての数値の平均を返したいと思います。
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
Test1の出力全体をgrepするには、次のようにします。
egrep -rh 'Test1: Avg. length.*' /home/timo/Documents
数字だけをgrepする方法がわかりません。頑張った
egrep -rhP '(?<=length )\d+' /home/timo/Documents
しかし、エラーが発生しました。
grep: conflicting matchers specified
誰でも私を助けることができればとても感謝します!
答え1
次の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
これにより、入力ファイル内のorで始まる行とTest2
合計フィールド4と6(それぞれ「長さ」と「時間」)が解析されます。また、データカウンタも増加しますn
。最後に、平均値(データが見つかった場合)またはエラーメッセージを印刷します。
少なくとも1つのファイルが存在すると確信している場合は、次のように単純化できます。
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
すべてのファイルが別々のサブフォルダーにあるように見えるため、方法はシェルによって異なります。最も簡単な場合は試してみてください。
awk -F'[ ,:]+' ' ... ' subdir*/file*.txt
答え2
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
sed '/^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