Mesclar arquivos csv com condições

2

Eu tenho 2 arquivos CSV para cada data ( csv_2014_4_15 e csv_2014_4_16 ), com estrutura básica e algumas colunas exclusivas, conforme abaixo.

id,name,created_at,updated_at,other columns

12, joe, 2013-1-1 18:30, 2014-2-1 12:00
56, bob, datetime, datetime

Eu quero mesclar os 2 arquivos csv com base nessas condições. Meu código até agora é como abaixo.

if (csv_date_x.id == csv_date_x+1.id)
{
   if(csv_date_x.updated_at < csv_date_x.updated_at)
         add csv_date_x+1 row into out.csv
}
else {
   if(csv_date_x+1.created_at == TODAY (yyyy-mm-dd)
         add csv_date_x+1 row into out.csv
}
    
por user3696932 11.07.2014 / 15:19

2 respostas

3

Tente isto:

$ awk -F',' -v t="$(date +"%Y-%-m-%-d")" '
    FNR == NR {
        u[$1] = $4;
        next;
    }
    $4 > u[$1] {
        print;
        next;
    }
    t ~ $3
' file_1 file_2

Explicação

  • Recebemos hoje a data, salve na variável t
  • Ao ler o arquivo_1 FNR == NR , salvamos cada tempo atualizado de cada ID no array associativo u , a chave é id, o valor é atualizado.
  • Durante a leitura do arquivo_2:

    • Se a data de atualização do ID, $4 maior do que o tempo atualizado de id id salvar na matriz u ( $4 > u[$1] ), imprimiremos a linha e passaremos para a próxima linha.
    • Se a condição acima for false, verificamos se a data de criação da linha atual é hoje, t ~ $3 , ou seja, "2014-7-11" ~ "2014-7-11 12:00" , se for verdade, imprima a linha.
por 11.07.2014 / 15:53
2

Suponho que por csv_date_x você quer dizer csv_2014_4_15 e csv_date_x + 1 significa csv_2014_4_16. Mas de acordo com o seu pseudo-código você nunca usa nenhuma linha de csv_date_x, então isso é mais um filtro do que uma mesclagem e você acaba com um subconjunto de csv_2014_4_16.

Esta é uma tarefa de programação não trivial, mas posso apontar você em uma direção lucrativa.

Esse tipo de coisa pode ficar difícil se você tiver que lidar com aspas que escaparam nos dois primeiros campos. Eu suponho que você não faz.

Também presumo que você possa comparar esses dois arquivos linha por linha, já que você não especificou.

Você precisará primeiro normalizar seus arquivos csv para que meses e datas sejam sempre dois dígitos (zeros à esquerda). Então eles podem ser comparados textualmente, e isso é muito fácil com awk . Algo como:

sed 's/-\([1-9]\)/-0/'

(isto assume que você não tem nenhum hífen em seus nomes, ids ou "outras colunas", você precisará de uma abordagem diferente, provavelmente correspondendo mais cuidadosamente aos padrões de data e possivelmente restringindo aos campos 3 e 4).

Use o programa date para gerar a data de hoje no formato de saída que corresponda aos seus campos e passe isso como uma variável para awk a ser usada:

awk -v Today=$(date +"%Y-%m-%d %H:%M") -v File1=csv_2014_4_15 -v File2=csv_2014_4_16 '
{ getline line1 < File1;
  getline line2 < File2;
  split(line1, f1, ",");
  split(line2, f2, ",");
}
f1[1] == f2[1] { ...; next } # compare IDs this is your first 'if' clause
{ ... } # this is your else clause since the previous ended with "next"

Você está em boa forma nesse ponto. f1 contém os campos da linha do Arquivo1 e f2 contém os campos da linha do Arquivo2. Você pode comparar ids (por exemplo, f1 [1] e f2 [1]) e datas (por exemplo, f1 [2] para criar f1 [3] para atualização). e imprima as linhas desejadas. Você pode comparar com Today para a data de hoje.

Note que você pode ficar mais sofisticado e fazer a normalização do formato de data em awk dividindo os 3º e 4º campos em - , mas eu acho mais fácil com um sed pass primeiro.

Observe também que Hoje contém data e hora. Se você quiser apenas comparar a data, pode soltar isso da especificação do comando date , mas também precisará dividir o campo csv para separar o tempo antes de comparar.

    
por 11.07.2014 / 16:39

Tags