Como posso encontrar quais arquivos csv estão relacionados (por exemplo, ter referências de chave estrangeira) para outros?

3

Um fornecedor externo me forneceu um dump de dados de mais de 20 tabelas como arquivos * .csv. Sua documentação está faltando, então eu tenho que percorrer os arquivos manualmente para descobrir quais arquivos estão 'relacionados' em um sentido RDBMS. Existe uma maneira de eu descobrir quais arquivos têm o mesmo padrão de string e imprimi-lo perfeitamente?

Atualmente estou fazendo isso e vinculando-os manualmente:

$> head -n 1 *.csv

Isso me dá uma saída como

==> EVO_ANGLE.csv <==
"evo_ang_id","angle_description"

==> EVOP_IMAGE.csv <==
"evop_image_id","evop_id","evo_ang_id","evo_collection","file_format","image_name","image_path", "image_type"

==> IMAGE_TYPE.csv <==
"id","image_type","group","description"

Como você pode ver, os arquivos EVO_ANGLE e EVOP_IMAGE estão relacionados com evo_ang_id e EVOP_IMAGE e IMAGE_TYPE têm o image_type em comum.

Existe uma maneira melhor para eu imprimir esta informação: Onde para cada arquivo eu posso ver quais outros arquivos têm o campo?

Meu melhor crack é escrever um script de shell que faça o seguinte na ordem:

  1. Pegue a primeira linha de cada arquivo e armazene em um mapa em uma matriz
  2. Para cada palavra em cada linha, encontre onde na matriz aparece
  3. Imprima a saída após agrupar essas informações.

Esta é uma tarefa árdua e exigirá uma depuração justa para acertar e direcionar a saída do console para ser mais rápida. Existe uma maneira melhor? Algum truque com combo cut / join / grep?

    
por PhD 24.02.2017 / 00:45

2 respostas

2

Se você está procurando em qual arquivo um determinado atributo pertence, você pode usar awk .

Desde que seus arquivos csv se pareçam com:

$ for i in *.csv; do echo $i; head -n1 $i; echo; done
EVO_ANGLE.csv
"evo_ang_id","angle_description"

EVOP_IMAGE.csv
"evop_image_id","evop_id","evo_ang_id","evo_collection","file_format","image_name","image_path", "image_type"

IMAGE_TYPE.csv
"id","image_type","group","description"

O comando awk a seguir reverterá os atributos e nome do arquivo:

$ awk -F', *' '                  # field separator = comma and optional spaces
      FNR==1{                    # Parse only the first line of each file.
         for(i=1;i<=NF;i++)             # Loop through all fields, and store them
            a[$i]=a[$i] " " FILENAME    # in an array together with the filename.
      }
      END{                          # When all files parsed, 
         for(i in a) print i,a[i]   # print the content of the array
      }' *.csv
"image_name"  EVOP_IMAGE.csv
"evo_collection"  EVOP_IMAGE.csv
"image_path"  EVOP_IMAGE.csv
"file_format"  EVOP_IMAGE.csv
"image_type"  EVOP_IMAGE.csv IMAGE_TYPE.csv
"evop_id"  EVOP_IMAGE.csv
"evop_image_id"  EVOP_IMAGE.csv
"id"  IMAGE_TYPE.csv
"evo_ang_id"  EVO_ANGLE.csv EVOP_IMAGE.csv
"description"  IMAGE_TYPE.csv
"group"  IMAGE_TYPE.csv
"angle_description"  EVO_ANGLE.csv

Se você precisar filtrar os atributos que pertencem a vários arquivos, use o seguinte:

$ awk -F', *' 'FNR==1{for(i=1;i<=NF;i++) a[$i]=a[$i] " " FILENAME}END{for(i in a) print i,a[i]}' *.csv | awk 'NF>2'
"image_type"  EVOP_IMAGE.csv IMAGE_TYPE.csv
"evo_ang_id"  EVO_ANGLE.csv EVOP_IMAGE.csv
    
por 24.02.2017 / 09:13
2

Aqui está uma versão centrada no bash; parece muito semelhante a versão awk do oliv

unset fileheads fields
declare -A fileheads
declare -A fields
for f in *.csv
do 
  IFS=, fileheads[$f]=$(head -n1 "$f");
  set -f
  for field in ${fileheads[$f]}
  do
    fields[$field]+=x
  done
  set +f
done

for field in ${!fields[*]}
do
  [[ ${#fields[$field]} -gt 1 ]] || continue 
  for file in ${!fileheads[*]}
  do
    [[ ${fileheads[$file]} =~ $field ]] && echo "$file has $field"
  done
  echo
done

Isso reúne os campos (linha 1) de cada arquivo na matriz fileheads associativa, indexada pelo nome do arquivo. Ele também reúne uma lista de quantas vezes ele é visto em cada nome de campo. Assumimos aqui que as vírgulas não aparecem nos próprios nomes dos campos.

Em seguida, percorremos todos os campos conhecidos; se algum deles for visto mais de uma vez, percorremos os arquivos (os índices na matriz fileheads ) para ver se algum deles contém esse campo. Pelo menos dois arquivos devem corresponder a esse critério; seus nomes de arquivos e campos vinculados são apagados, seguidos por uma linha em branco, por questões de legibilidade.

Execução da amostra:

entrada

$ head -n1 *.csv
==> EVOP_IMAGE.csv <==
"evop_image_id","evop_id","evo_ang_id","evo_collection","file_format","image_name","image_path","image_type"

==> EVO_ANGLE.csv <==
"evo_ang_id","angle_description"

==> IMAGE_TYPE.csv <==
"id","image_type","group","description"

saída

EVOP_IMAGE.csv has "evo_ang_id"
EVO_ANGLE.csv has "evo_ang_id"

EVOP_IMAGE.csv has "image_type"
IMAGE_TYPE.csv has "image_type"
    
por 24.02.2017 / 22:21