カテゴリー
【実践!CSVデータ検索スクリプト作成編】条件を与えて検索結果をCSVデータで出力するスクリプト
※ 当ページには【広告/PR】を含む場合があります。
2021/04/10
2022/08/07
CSVデータの検索に特化したエクセルでいうところのVLOOKUP関数のような機能をもつスクリプトツールを作成してみる特集の第1回目です。
今回は読み込んだCSVデータの特定の1列を検索キーとして、指定した検索キーリストからヒットした要素を順にピックアップしてCSV形式で表示するスクリプトを作成してみます。
なお、シェルコマンドでのスクリプト作成の基本は以前の記事で集中的に取り上げていましたので、そちらの方も参考にしてください。
はじめに

当サイトではオフィス業務のComputer-Aidedなハイブリッドな方法を模索し、より効率的なExcel業務を実現したい多忙なオフィスワーカー向けの主にAwkとSedを使うシェル講座です。
シェルスクリプトはどこでもどんなOSでも基本的に使えて、しかも一度使い方を覚えると、Excelと組み合わせて最高に効率の良いオフィスワークツールが作れることでしょう。
作成するスクリプトツールの概要
まずは例題として以下のような社員リストのCsvデータの中を検索するとします。
下のコマンドで
employee.csv
$ cat <<EOF > employee.csv
山下モゲ雄,営業部,本社,3年
島田フガ子,経理部,名古屋支部,15年
岡田ピポ太,製造部,山口工場,8年
佐藤ゴバ文,製造部,山口工場,11年
沢口モフ代,人事部,本社,4年
銭形ガメ吉,海外部,メキシコ支部,11年
上岡ムメ美,営業部,本社,23年
京谷マハ次,製造部,山口工場,3年
園田フマ由,人事部,本社,17年
山田ケム紀,営業部,本社,15年
田川ポゥ子,製造部,ベトナム工場,12年
満田クタ郎,営業部,本社,2年
島寺ルン大,営業部,本社,18年
香下ウル蔵,製造部,山口工場,5年
田頭モフ雄,営業部,名古屋支部,16年
蒲田ウオ奈,海外部,メキシコ支部,9年
郷田ポポ生,営業部,名古屋支部,4年
梅岡ボル伍,経理部,本社,25年
亀川ヲル士,製造部,山口工場,14年
EOF
例えば社員の名前の一部を検索キーとしてキーワードをリストとして引数に与えて、CSVデータから該当の行を順番に引っこ抜くようなツールスクリプトが今回作成したいスクリプトとします。
コマンド実行のイメージで言うと以下のような感じです。
$ ./simple_finder.sh -l '山田','佐藤','モフ雄' employee.csv
#山田の項目...
#佐藤の項目...
#モフ雄の項目...
なお、検索した場合に重複をどう取り扱うか、と言う課題も当然出てくると思います。
例えば、このスクリプトで言うと佐藤Aさんと佐藤Bさんがデータとして同時に存在する場合にどう取り扱うかetc..
今回の記事ではCSVデータに重複がないことを想定していますが、重複のあるケースは後日解説していく予定です。
Bashスクリプトツールの雛形作成
まずは今回のスクリプトツール作成に当たって、コマンドに外部から引数を与えられるようにしておきます。
本記事で作成するスクリプトの実装例として、以前
今回は以下のようにスクリプトの概形を仕立て直しておきます。
#!/bin/bash
usage_exit() {
echo "USAGE: $(basename $0) [-l key_list] [-h help] [input_file]" 1>&2
exit 1
}
noarg_err() {
echo "ERROR: must provide key_list!" 1>&2
exit 1
}
noinputfile_err() {
echo "ERROR: not allowed input file to be empty!" 1>&2
exit 1
}
while getopts l: OPT; do
case $OPT in
l ) KEY_LIST="$OPTARG"
;;
\? ) usage_exit
;;
esac
done
shift $((OPTIND - 1))
if [ -z "$KEY_LIST" ]; then
noarg_err
fi
if [ -z "$1" ]; then
noinputfile_err
fi
echo "FILE: $1, KEY_LIST: ${KEY_LIST}"
一旦ここでこのスクリプトが引数を受けて動作するかを
simple_finder.sh
$ chmod +x simple_finder.sh
$ ./simple_finder.sh -l '山田','佐藤','モフ雄' employee.csv
FILE: employee.csv, KEY_LIST: 山田,佐藤,モフ雄
Awkによる検索メソッドの実装
では上記のスクリプトの雛形にAwkを使った検索関数を作成していきます。
Awkでの文字列検索の基礎は、match関数の使ったやり方では以下のリンクの記事で解説していました。
またmatch関数ではなくてもAwkでは強力な正規表現による判定も使えることを以下の記事でも解説していました。
今回のケースでは正規表現のほうがmatch関数よりもお手軽に使えるので、こちらのテクニックでコーディングしてみます。
では先程のスクリプトに以下のように追加編集してみます。
#!/bin/bash
#....
#....中略
#....
echo "FILE: $1, KEY_LIST: ${KEY_LIST}"
#👇①...☆ここから追加
PARR=($(echo "${KEY_LIST}" | tr ',' ' '))
for p in "${PARR[@]}"; do
awk -F"," '
$1 ~ /'"$p"'/ { print $0 }
' $1
done
このスクリプトの作成ポイントは、キーリストを配列化してfor...inループで回すことと、Awkスクリプトの部分を複数のシングルクォーテーションで区切って、その合間でダブルクオーテーションでシェルコマンド呼び出しを挟んでいることです。
awkスクリプト外部から変数を注入する方法は他に、-vオプションを使ったり、getline処理で外部コマンドからの処理を挟んだりすることもできます。
これを実行すると、
$ ./simple_finder.sh -l 山田,佐藤,モフ雄 employee.csv
FILE: employee.csv, KEY_LIST: 山田,佐藤,モフ雄
山田ケム紀,営業部,本社,15年
佐藤ゴバ文,製造部,山口工場,11年
田頭モフ雄,営業部,名古屋支部,16年
のように検索結果がCSV形式で得られました。
検索に引っかからない時の措置 〜 N/Aで埋めてみる
先程作成したスクリプトではリストのキーワードで探せなかった場合には何も起こらずにスキップされてしまいます。
$ ./simple_finder.sh -l 山田,佐川,モフ雄 employee.csv
FILE: employee.csv, KEY_LIST: 山田,佐川,モフ雄
山田ケム紀,営業部,本社,15年
田頭モフ雄,営業部,名古屋支部,16年
検索結果が無い場合にも何らかのレスポンスが欲しい場合があります。
以前、Excel風にエラーが発生した時に出る
#N/A
ということでここでも同じように、先程のスクリプトを再度以下のようにちょこっと編集します。
#!/bin/bash
#....
#....中略
#....
echo "FILE: $1, KEY_LIST: ${KEY_LIST}"
#👇①...☆Awkスクリプト部分を編集
PARR=($(echo "${KEY_LIST}" | tr ',' ' '))
for p in "${PARR[@]}"; do
awk -F"," '
$1 ~ /'"$p"'/ { last_macthed = $0; }
END { print last_macthed ? last_macthed : "'"$p"'?,#N/A,#N/A,#N/A"; }
' $1
done
修正のポイントは検索でマッチした場合の結果を保持させておいて、ENDアクションブロックでその結果を表示させるように変更しただけです。
もし検索結果が無い場合には、各セルを#N/A値で埋めたレスポンス行を生成して返すようにしています。
この修正したスクリプトを先程と同様に実行すると、
$ ./simple_finder.sh -l 山田,佐川,モフ雄 employee.csv
FILE: employee.csv, KEY_LIST: 山田,佐川,モフ雄
山田ケム紀,営業部,本社,15年
佐川?,#N/A,#N/A,#N/A
田頭モフ雄,営業部,名古屋支部,16年
となって、検索できなかったキーが明瞭に分かると思います。
まとめ
以上、コマンド形式でキーワードによるCSVデータのリスト検索を行うスクリプトツールの大まかな作成方法をAwkベースで作成してみました。
今回のスクリプトツールはかなりシンプルですので、検索する要素の重複などは一切考慮していませんでしたので、次回以降で重複させる・させないの挙動を制御させるような修正をネタに記事を更新していこうと思います。
記事を書いた人
ナンデモ系エンジニア
主にAngularでフロントエンド開発することが多いです。 開発環境はLinuxメインで進めているので、シェルコマンドも多用しております。 コツコツとプログラミングするのが好きな人間です。
カテゴリー