compare arquivos com base em duas colunas e adicione campo

compare arquivos com base em duas colunas e adicione campo

Tenho arquivos com datas e horas em colunas no formato "AAAA MM DD HHMM" mais uma variável (temperatura) e quero convertê-los para o formato AAAA DDD (e manter a hora e a temperatura como estão). Eles se parecem com isto, mas a mesma data aparece várias vezes no arquivo:

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

Criei um arquivo de índice (1980-2017) com a quantidade de dias a serem adicionados a cada data do primeiro arquivo para obter o dia acumulado do ano DDD (última coluna). O primeiro ano é assim (1980 foi um ano bissexto):

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

Estou tentando comparar os dois arquivos com base nas duas primeiras colunas e, se eles corresponderem, adicionar a quarta coluna do arquivo2 à terceira coluna do arquivo 1 e terminar com algo assim:

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

Consegui comparar as duas colunas dos arquivos e adicionar as duas colunas com o awk abaixo:

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

mas assim perco $ 4 e $ 5 (hora e temperatura). Existe uma maneira de combinar as duas funções do awk e obter $4 e $5 do arquivo1 também no resultado? Qualquer ajuda muito apreciada.

Responder1

É difícil testar porque você forneceu correspondências potenciais apenas para um único ano, mas

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

Responder2

Supondo que GNU datee bash(ou qualquer shell que processe a substituição por <(...)) e que os dados sejam armazenados no arquivo filecomo nos primeiros dados de exemplo da pergunta:

$ 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
  • O primeiro cuté usado em conjunto trpara transformar as datas nas três primeiras colunas dos dados de entrada para o formulário YYYY-MM-DD.
  • Isso é passado ao GNU datepara processamento em lote por meio de sua -fopção. Como saída solicitamos datas usando o formato %Y %j. %Yé o ano no formulário YYYYe %jé o dia do ano no formulário DDD.
  • Isso é colado junto com as duas últimas colunas do arquivo original (produzido pelo segundo cut) usando um único espaço como delimitador.

Esta é uma transformação direta dos dados originais para o resultado final, ignorando a necessidade do arquivo de índice que você criou.

informação relacionada