2つの列に基づいてファイルを比較し、フィールドを追加します

2つの列に基づいてファイルを比較し、フィールドを追加します

「YYYY MM DD HHMM」形式の列単位の日付と時刻、および変数 (温度) を含むファイルがあり、これを YYYY DDD 形式に変換したいと考えています (時間と温度はそのままにします)。ファイルは次のようになりますが、同じ日付がファイル内に複数回表示されます。

1980 01 01 0100 3.3
1982 04 11 0400 2.2
1985 12 04 0700 1.7
1995 12 31 1000 2.2

最初のファイルの各日付に追加される日数を指定して、年間累計日数 DDD (最後の列) を取得するインデックス ファイル (1980 ~ 2017) を作成しました。最初の年は次のようになります (1980 年はうるう年でした)。

1980 01 31  000
1980 02 29  031
1980 03 31  060
1980 04 30  090
1980 05 31  121
1980 06 30  152
1980 07 31  182
1980 08 31  213
1980 09 30  244
1980 10 31  274
1980 11 30  305
1980 12 31  335

最初の 2 つの列に基づいて 2 つのファイルを比較し、一致する場合はファイル 2 の 4 番目の列をファイル 1 の 3 番目の列に追加して、次のようになるようにしています。

1980 001 0100 3.3 
1982 101 0400 2.2 
1985 346 0700 1.7 
1995 365 1000 2.2

以下のように、awk を使用してファイルの 2 つの列を比較し、2 つの列を追加することができました。

awk -F' ' 'NR==FNR{c[$1$2]++;next};c[$1$2] > 0' junktemp matrix_sample | awk '{print $1, $3+$4}' 

しかし、この方法では $4 と $5 (時間と温度) が失われます。2 つの awk 関数を組み合わせて、結果に file1 の $4 と $5 も取得する方法はありますか? ご協力いただければ幸いです。

答え1

1年間の潜在的な一致しか提供していないため、テストするのは難しいですが、

awk 'NR==FNR{c[$1$2]=$4; next} ($1$2 in c) {$3 = sprintf("%03d", $3 + c[$1$2])} {print $1, $3, $4, $5}' file2 file1
1980 001 0100 3.3
1982 11 0400 2.2
1985 04 0700 1.7
1995 31 1000 2.2

答え2

GNUdateおよびbash(または でプロセス置換を実行する任意のシェル) を使用し、データが質問の最初の例のデータのように<(...)ファイルに格納されていると仮定します。file

$ paste -d ' ' <( date -f <( cut -d ' ' -f1-3 file | tr ' ' '-' ) +"%Y %j" ) \
               <( cut -d ' ' -f4-5 file )
1980 001 0100 3.3
1982 101 0400 2.2
1985 338 0700 1.7
1995 365 1000 2.2
  • 最初の はcutと一緒に使用され、tr入力データの最初の 3 列の日付を の形式に変換しますYYYY-MM-DD
  • dateこれは、オプションを通じてバッチ処理のためにGNU に渡されます-f。出力として、 の形式を使用して日付を要求します%Y %j%Yはフォーム上の年でありYYYY%jはフォーム上の日ですDDD
  • cutこれは、区切り文字として 1 つのスペースを使用して、元のファイル (2 番目で生成された) の最後の 2 つの列と一緒に貼り付けられます。

これは、作成したインデックス ファイルの必要性を回避して、元のデータから最終結果に直接変換するものです。

関連情報