カテゴリー
【Awk&Sed活用講座】CSVファイルから重複データを見つける&重複をカウントする
※ 当ページには【広告/PR】を含む場合があります。
2022/05/04
2022/09/30
思いついたときに書き綴るシェルスクリプトからのCSVデータ使いこなし講座です。
以前、AwkでCSVデータセット中の
そちらの記事ではCSVデータセットをマトリックス生データを意識して、セル要素の重複を操作することを中心に解説していました。
通常のCSVデータシートでの重複というと、人によってはインデックスキーを照らし合わせた際の
今回はCSVファイルからデータ中の「行要素」の重複を取り扱うテクニックを取り上げてみます。
Uniqコマンドで重複を操作する
まずはAwkやSedなどを使って技巧的なやり方に頼らずにシェルスクリプトの基本に従うと、
とりあえず例として以下の重複有りの従業員リストを対象に重複操作を考えます。
なお、ローカルにcsvテキストで保存して読み出しても良いのですが、今回は変数・
EMPLOYEE
$ EMPLOYEE=$(cat <<EOF
山下モゲ雄,営業部,本社,3年
島田フガ子,経理部,名古屋支部,15年
上岡ムメ美,海外部,メキシコ支部,8年
岡田ピポ太,製造部,山口工場,8年
佐藤ゴバ文,製造部,山口工場,11年
田川ポゥ子,人事部,本社,9年
沢口モフ代,人事部,本社,4年
銭形ガメ吉,海外部,メキシコ支部,11年
上岡ムメ美,営業部,本社,23年
京谷マハ次,製造部,山口工場,3年
園田フマ由,人事部,本社,17年
山田ケム紀,営業部,本社,15年
田川ポゥ子,製造部,ベトナム工場,12年
満田クタ郎,営業部,本社,2年
島寺ルン大,営業部,本社,18年
香下ウル蔵,製造部,山口工場,5年
田頭モフ雄,営業部,名古屋支部,16年
岡田ピポ太,営業部,本社,4年
蒲田ウオ奈,海外部,メキシコ支部,9年
郷田ポポ生,営業部,名古屋支部,4年
梅岡ボル伍,経理部,本社,25年
香下ウル蔵,営業部,名古屋支部,2年
岡田ピポ太,製造部,山口工場,11年
亀川ヲル士,製造部,山口工場,14年
EOF
)
では、
Uniq
uniqの出来ることは基本に
重複行の出現回数を調べる
重複していない行だけ出力する
重複した行だけ出力する
単純な重複をテキストの各行に行うことに特化したコマンドになります。
uniq単体だと複雑な処理は不可能ですので、CSVの任意の列だけ取り出すため
Cutコマンド
Sortコマンド
$ echo "$EMPLOYEE" | cut -f1 -d, | sort | uniq
上岡ムメ美
亀川ヲル士
京谷マハ次
佐藤ゴバ文
園田フマ由
山下モゲ雄
山田ケム紀
岡田ピポ太
島寺ルン大
島田フガ子
梅岡ボル伍
沢口モフ代
満田クタ郎
田川ポゥ子
田頭モフ雄
蒲田ウオ奈
郷田ポポ生
銭形ガメ吉
香下ウル蔵
ということで、Uniqコマンドはデータから重複を見つけるだけになります。
さほど応用は期待できません。
Awkで重複を見つける
AwkでCSVデータの重複を取り扱うメリットには、列(カラム)番号を個別に制御するような操作に向いています。
重複を除するのに良く紹介されている使い方は、
$ echo "$EMPLOYEE" | awk -F, '!name[$1]++ { print $0; }'
山下モゲ雄,営業部,本社,3年
島田フガ子,経理部,名古屋支部,15年
上岡ムメ美,海外部,メキシコ支部,8年
岡田ピポ太,製造部,山口工場,8年
佐藤ゴバ文,製造部,山口工場,11年
田川ポゥ子,人事部,本社,9年
沢口モフ代,人事部,本社,4年
銭形ガメ吉,海外部,メキシコ支部,11年
京谷マハ次,製造部,山口工場,3年
園田フマ由,人事部,本社,17年
山田ケム紀,営業部,本社,15年
満田クタ郎,営業部,本社,2年
島寺ルン大,営業部,本社,18年
香下ウル蔵,製造部,山口工場,5年
田頭モフ雄,営業部,名古屋支部,16年
蒲田ウオ奈,海外部,メキシコ支部,9年
郷田ポポ生,営業部,名古屋支部,4年
梅岡ボル伍,経理部,本社,25年
亀川ヲル士,製造部,山口工場,14年
とするだけで簡単に強力な重複操作がAwkだけで実現します。
なお、先程のAwkのスクリプト部分はもっと圧縮できて、
$ echo "$EMPLOYEE" | awk -F, '!_[$1]++'
と出来るのは良く知られたところです。
Sedで重複を見つける
先程の項目で紹介したように、重複操作においてソート・対象列抽出・正規表現ともに利用できるAwkの独壇場であることが分かりますが、たまにAwk(gawk)が使えない環境もあります。
Sedでもかなり頑張れば重複操作は出来なくはありません。
ただし、
uniq同様、離れた行に重複する要素が存在すると、重複する要素を探す処理に時間がかかるので、一度sortを読み込んで連続行に揃えおく処理をはさみます。
さらに入力各行ごとの比較はできるものの、柔軟に部分文字を抽出してからの比較となるとかなり厳しい処理が必要で、やはりCutコマンドでターゲットのCSV列を抽出する下処理が必要です。
Sedでややこしいのが、日本語を含むUnicode文字では正規表現のキャプチャが出来ないかもしれないので、sedコマンド前に、
LC_ALL=C
$ echo "$EMPLOYEE" | sort | cut -f1 -d, | LC_ALL=C sed -e '
$!N #最終行以外は全て先読みで次の行をパターンスペースに改行&追加
/^\(.*\)\n\1$/!P #2行目に同じ行パターン来た場合、パターンスペースの最初の改行までを表示
D #パターンスペースを空にして次の入力行からプログラムを繰り返す
'
#👇出力
上岡ムメ美
亀川ヲル士
京谷マハ次
佐藤ゴバ文
園田フマ由
山下モゲ雄
山田ケム紀
岡田ピポ太
島寺ルン大
島田フガ子
梅岡ボル伍
沢口モフ代
満田クタ郎
田川ポゥ子
田頭モフ雄
蒲田ウオ奈
郷田ポポ生
銭形ガメ吉
香下ウル蔵
...Uniqコマンド相当のことしか出来ないのに、Sedスクリプトの実装はNやらPやらDと、利用上奥の深いコマンドを駆使する必要があります。
この点において、Sedの勉強には良いのですが、本番の重複操作はやるべきではないでしょう。
記事を書いた人
ナンデモ系エンジニア
主にAngularでフロントエンド開発することが多いです。 開発環境はLinuxメインで進めているので、シェルコマンドも多用しております。 コツコツとプログラミングするのが好きな人間です。
カテゴリー