複数ファイルのn行平均を1つの平均マスターファイルにマージ

複数ファイルのn行平均を1つの平均マスターファイルにマージ

8行の値とテキストを含む3つのファイルがあります。 3つのファイルすべてで各行の平均を取得し、その平均で新しいファイルを印刷しようとしています。以下は、同じ名前の形式を持つ3つのサンプルファイルです。testfile1.1、testfile1.2、testfile1.3

テストファイル1.1

1
2048
8
5
5
4
9
Lat:1

テストファイル1.2

1
2048
10
7
7
4
9
Lat:1

テストファイル1.3

1
2048
3
6
3
4
6
Lat:7

出力ファイルを次のように作成したいです(平均化後)。

平均ファイル1

1
2048
7
6
5
4
8
Lat:3

これが私がやろうとしていることに意味があることを願っています!

私はawkとsedのさまざまな組み合わせを試してみましたが、3〜4行のデータに適していましたが、実際のデータには40を超えるファイル名を含む2000行を超えました。

編集:だから、印刷したい数字を制御する方法と、浮動小数点とよりよく一致するように正規表現を編集する方法を理解できます。

(この質問を別の質問にして、この質問を削除する必要があるかどうか教えてください!)

私の実際のデータには、テキストと平均を求めたい値を含む他の行がたくさんあります。追加の文字列を作成しようとしましたが、さらに混乱しました。私の実際のファイルの特定の行では、行のテキストの印刷、実際のデータの平均化、テキストとデータの平均による行のコピー、日付と時刻の平均化など、さまざまなコマンドが必要です。

以下は2つのファイルのコピーです(各行には、私がしたいことがコメントとして表示されています)。

豆腐1.1

ABCDEFGH #print text into output file (same on both files)
1     # Take average of values across all the files in this line
2048  # Take average of values across all the files in this line
8     # Take average of values across all the files in this line
5     # Take average of values across all the files in this line
5     # Take average of values across all the files in this line
4     # Take average of values across all the files in this line
9.5   # Take average of values across all the files in this line
1     # Take average of values across all the files in this line
90.00  # Check and make sure value in this line across print if same
Sprite # check and see if text is same across all values and print if same
cats10   # check and see if text is same across all values and print if same
07/02/20 # See below for explantion on next 3 lines
08:32
08:32
290.000000 # average across all 3 files on this line
10.750000 # average across all 3 files on this line
SCANS23   # output should be SCANS "average of values"
INT_TIME57500 # output should be INT_TIME with sum of all values
SITE northpole   #Check if all lines are same if so print line
LONGITUDE -147.850037  # Output should be LONGITUDE%f
LATITUDE 64.859375     # Output should be LONGITUDE%f

行13はデータのソース日付、行14は開始時刻と終了時刻です。たぶん、ある種の日付を10進数のコマンドとして使用するかもしれません。日付の平均を求める方法はありますか?あるデータを07/02/20に取得し、別のデータを07/02/18に取得した場合、出力は07/02/19になりますか?時間平均も考慮されます。

豆腐1.2

ABCDEFGH #print text into output file (same on both files)
1     # Take average of values across all the files in this line
2048  # Take average of values across all the files in this line
10    # Take average of values across all the files in this line
7     # Take average of values across all the files in this line
7     # Take average of values across all the files in this line
4     # Take average of values across all the files in this line
8   # Take average of values across all the files in this line
1     # Take average of values across all the files in this line
90.00  # Check and make sure value in this line across print if same
Sprite # check and see if text is same across all values and print if same
cats10   # check and see if text is same across all values and print if same
07/02/20 # See below for explanation on next 3 lines
08:32
08:32
290.000000 # average across all 3 files on this line
10.750000 # average across all 3 files on this line
SCANS23   # output should be SCANS "average of values"
INT_TIME57500 # output should be INT_TIME with sum of all values
SITE northpole   #Check if all lines are same if so print line
LONGITUDE -147.850037  # Output should be LONGITUDE%f
LATITUDE 64.859375     # Output should be LONGITUDE%f

私のスクリプトに複数の文字列開始値を含めようとする努力はうんざりしており、非常に速く混乱しています。

awk -F: '
  FNR==1     { c++ };
  /^LATITUDE/    { a[FNR] += $6 };
  /^SCANS/    { a[FNR] += $2 };
  /^[+-]?([0-9]*[.])?[0-9]+$/ { a[FNR] += $1 };

  END {
    for (i in a) {
      printf (i==22 ? "LATITUDE%f": i==18 ? "SCANS%2.3f": "%f") "\n", a[i] / c
    }
  }' tofu1.* > askforhelp

これは私に与える

$ more askforhelp

90.000000
LATITUDE0.000000
290.000000
10.750000
SCANS0.000
1.000000
2048.000000
6.333333
4.666667
5.000000
4.000000
7.833333
2.666667

また、一度に複数のテキスト文字列を追加しようとしましたが、この試みではまったく出力が出ていないため、非常に混乱しました。

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/lmdjeu/test/test1.* > /home/lmdjeu/test/askforhelp

ベストアンサー1

$ awk -F: '
  FNR==1     { c++ };
  /^Lat:/    { a[FNR] += $2 };
  /^[0-9]+$/ { a[FNR] += $1 };

  END {
    for (i in a) {
      printf (i==8 ? "Lat:%i" : "%i") "\n", a[i] / c
    }
  }' Testfile1.* > Averagefile1

$ cat Averagefile1
1
2048
7
6
5
4
8
Lat:3

変数を使用してc読み取ったファイル数を計算します。この変数は、ファイルの最初の行()を読むたびに c増加します。入力レコード(行番号)カウンタはawkによって自動的に設定され、入力ファイルが読み取られるたびにリセットされます。FNR==1FNR

また、配列を使用してa各入力行の累積合計を格納し、配列へFNRのインデックスとして使用されます。行に数字のみが含まれている場合、行の最初の(唯一の)フィールドが行の配列要素に追加されます。文字列で始まる場合は、Lat:2番目のフィールドが追加されます。

すべての入力ファイルを読み取って処理した後、ENDブロックが実行されます。これは配列を繰り返し、各要素の合計をファイル数で割った値を出力します。 8行を除くすべての行は整数でのみ印刷されます。

8行の場合、整数の前に文字列が付きますLat:。スクリプトはこれを達成するためにawkの三項演算子を使用します。condition ? result_if_true : result_if_false

おすすめ記事