Bash:2つのcsvファイルのデータ接続

Bash:2つのcsvファイルのデータ接続

さまざまなユーザーデータを含む2つのcsvファイルがあり、共通フィールド(ユーザー名)を共有します。

file A:
username ; Fullname ; mail
Bob      ; Bob Hope ; [email protected]

file B:
username ; LastLogonTime  ; AccountStatus (locked=0 or unlocked=1)
Bob      ; 2018-10-01 etc.; 0

監査の目的で Bash を使用して A を繰り返し、B と交差させてアカウントがロックされていることを確認したいと思います。この場合、ユーザにAのメールアドレスにメールを送ることができる。

awk -F";"

Aをスキップできます。簡単です。しかし、Bに対してクロスチェックループを実行しようとするとパニックになります。

ベストアンサー1

を使用して、awk最初に2番目のファイルからアカウントがロックされているユーザーのユーザー名を読み、次に最初のファイルからそのユーザーのEメールアドレスを抽出します(その後、Eメールを読むためにログインする必要はありません)。

awk -F ';' 'NR == FNR && $NF == 0    { names[$1] }
            NR != FNR && $1 in names { print $NF }' B.csv A.csv

これは、2つのファイルの各ユーザー名の周りに同じ数のスペースがあると仮定します。そうでない場合は、使用する-F ' *; *'区切り文字にスペース文字を含めることができますawk。また、;データに含まれる文字がないとします。

NRは現在のレコード全体のレコード(行)番号で、FNR現在のファイル内で同じですが同じ番号です。その場合は、コマンドライン()で提供されている最初のファイルから読み込みます NR == FNR。は現在のレコードのフィールド(列)の数、は最後のフィールドのデータです(そして最初のフィールドのデータです)。B.csvNF$NF$1

上記のコードは、names最初のファイル()から読み取られたロックされたユーザーのユーザー名としてキー付きの連想配列/ハッシュを使用しますB.csv。これがこの配列のキーであれば$1 in names真です。$1

ループに入れます。

awk -F ';' 'NR == FNR && $NF == 0    { names[$1] }
            NR != FNR && $1 in names { print $NF }' B.csv A.csv |
while read addr; do
    printf 'Would send an email to "%s"\n' "$addr"
    #mail -s 'Account locked' "$addr" <template-email.txt
done

または同様の条項。繰り返しこの方法で電子メールアドレスを読むと、周囲のすべてのスペースが削除されます。上記のループは電子メールを送信しませんが、電子メールを送信する必要があるアドレスを印刷します。実際に電子メールを送信するには、以前の#コンテンツを削除し、mailその中に電子メール形式を作成しますtemplate-email.txt(しかし、異なることもできます)。


使用csvkit:

csvjoin -d ';' -c 1 A.csv B.csv |
csvgrep -c 5 -m False |
csvcut -S -c 3 | sed 1d

CSVkitは、CSVファイルを処理するためのCSV解析ツールを提供します。 CSVデータが「単純」でない場合、つまり埋め込み文字などを参照するためにCSVルールを使用する場合は、これを行う必要があります。;上記のパイプラインは

  1. ユーザー名に基づいて2つのファイルを関連付けます(スペースが重要です)。
  2. ロックされたユーザーのデータを抽出します(この時点で、遺言はパイプラインからこの時点に0変更されました)。False
  3. メールアドレスを抽出します。
  4. CSVヘッダーを削除します(最後のsedコマンドを使用)。

おすすめ記事