他のファイルに関連するcsvファイル(外部キー参照を含むファイルなど)を見つける方法は?

他のファイルに関連するcsvファイル(外部キー参照を含むファイルなど)を見つける方法は?

外部ベンダーは、* .csvファイル形式で20を超えるテーブルのデータダンプを提供しました。文書が不足しているため、RDBMSの意味で「関連」ファイルを見つけるには、ファイルを手動で参照する必要があります。どのファイルに同じ文字列パターンがあるかを見つけて、きれいに印刷する方法はありますか?

現在私はこれを行い、手動で接続しています。

$> head -n 1 *.csv

これは私に次のような結果を与えます

==> 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"

ご覧のとおり、ファイルとEVO_ANGLEは関連しており、EVOP_IMAGE共通点があります。evo_ang_idEVOP_IMAGEIMAGE_TYPEimage_type

この情報を印刷するより良い方法はありますか?各ファイルについて、そのフィールドを持つ他のファイルをどこで確認できますか?

これに対する最善の解決策は、以下を順番に実行するシェルスクリプトを作成することです。

  1. 各ファイルの最初の行を取得し、配列のマップに保存します。
  2. 各行の各単語について、配列内のその単語が表示される場所を探します。
  3. この情報を集めて印刷します。

これは面倒なことであり、正常に動作するには多くのデバッグが必要で、コンソール出力を表示する方が速いかもしれません。もっと良い方法がありますか? Cut / Join / Grepの組み合わせに関するヒントはありますか?

答え1

特定の属性が属するファイルを探している場合は、使用できますawk

csvファイルが次のようになっているとします。

$ 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"

次のawkコマンドは、属性とファイル名を逆に変更します。

$ 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

複数のファイルに属する属性をフィルタリングする必要がある場合は、次のコマンドを使用します。

$ 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

答え2

これはbash中心のバージョンと非常に似ているようです。オリーブのawkバージョン

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

これにより、各ファイル(行1)のフィールドがfileheadsファイル名で索引付けされた連想配列に収集されます。また、各フィールド名の発生回数のリストを収集します。ここでは、フィールド名自体にカンマが表示されないと仮定します。

次に、既知のすべてのフィールドを繰り返します。いずれかが複数回表示される場合は、ファイル(配列のインデックスfileheads)を繰り返して、対応するフィールドが含まれていることを確認します。読みやすくするために、少なくとも2つのファイルがこの基準を満たす必要があり、そのファイル名とリンクフィールドがエコーされ、その後に空白行が表示されます。

実行例:

入力する

$ 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"

出力

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"

関連情報