【シェルと遊ぼう】日本のコロナ感染者情報取得スクリプト その2(列項目の抽出と並べ替え)

はじめに

こちらの記事の続き。

作るもの

今回は指定した列項目のみ抜き出す処理について。

  1. データベースの作成・更新と全行全項目の出力
  2. 全感染者の指定項目を取得 (列の抽出,並べ替え) <== 今回はこれ
  3. 指定項目の条件でフィルタ (行の抽出)
  4. 指定項目の内訳集計 (出現回数のカウント)

以降では、前回同様作るスクリプト名をcovidとした前提で説明する。

実行イメージ

以下のように、引数で欲しい列名を欲しい順で指定する。

$ covid date age sex area2 status
確定日,年代,性別,居住地,状態
2020/01/15,30,男性,神奈川県,退院
2020/01/24,40,男性,中華人民共和国,退院または死亡
2020/01/25,30,女性,中華人民共和国,退院または死亡
 ...
 ...
2020/05/13,不明,不明,東京都,

列項目について

前回も載せたけど、指定可能な列項目は以下。

項目 パラメータ 備考 出力例
ID id データの通し番号。元データの「通し」 1/2/3...
確定日 date PCR検査の陽性確定日 '2020/05/13'など
受診都道府県 area1 陽性確定時に感染者が受診していた医療機関がある都道府県。空港名もある... 東京都/沖縄県/不明など
居住地 area2 感染者の住居都道府県または居住国 東京都/沖縄県/不明など
居住地(詳細) area3 元データ項目では「キー」。居住都道府県と同じデータも多数 東京都/沖縄県那覇市/不明など
年代 age 感染者の年代。元データは100歳以上も90に含むっぽい 0/10/20/30/40/50/60/70/80/90/100/不明
性別 sex 感染者の性別 男性/女性/不明
職業 job 感染者の職業。記載がある件数が少なく同職種でも記載に統一感なし... 会社員/看護師/無職/不明(#1)など
備考 note 詳細地区や年齢やその他補足情報っぽい 足立区/100歳以上/再陽性
状態 sts 感染者の状態。元データの「ステータス」と「無症状病原体保有者」の組み合わせ 死亡/退院/退院または死亡(国内無症状)/空欄

年代については元データをスクリプトで以下のように加工して出力する。

元データ 出力 備考
0-10 0 10歳未満
90 100 備考に「100歳以上」と記載がある場合のみ
空欄 不明

コード

列の並び替え関する主要コードは以下。

コード全体はこちらを参照されたし。

引数チェック

列名が不正でないかは以下でチェック。怠いコードですな。
ERR_MSGが空でなかったらメッセージを出力して実行終了する。

  for field in "$@";do
    case $field in
    id | date | area1 | area2 | area3 | age | sex | job | note | sts ) ;;
    * ) ERR_MSG="invalid field-name '$field'" ;;
    esac
  done

引数の列名をawkの列位置へ

引数で列項目名を指定した場合、awkの列位置に置き換える。

OUTPUT_ITEMS='$0'
if [ $# -gt 0 ]; then
  OUTPUT_ITEMS=`echo "$*" | $NAME_TO_POS | sed -e 's/[ ]\{1,\}/,/g'`
fi

上記の$NAME_TO_POSにセットしている関数は以下。
またまた怠いコードですな。

item_name_to_pos(){
  sed -e 's/id/$1/g'    \
    -e 's/date/$2/g'    \
    -e 's/area1/$3/g'   \
    -e 's/area2/$4/g'   \
    -e 's/area3/$5/g'   \
    -e 's/age/$6/g'     \
    -e 's/sex/$7/g'     \
    -e 's/job/$8/g'     \
    -e 's/note/$9/g'    \
    -e 's/sts/$10/g'
}

列位置は、このスクリプト用に作っているDBファイル($ITEM_DB_FILE)の列位置。
元データのCSVの列位置じゃない点に注意。

指定列項目を出力

出力するのは前回と同じ以下のコード。
先程のコードで$OUTPUT_ITEMSにはawkで使える列位置が入っているので、
これだけで好きな列を自由に指定できちゃう。

else
  # output pickup recodes
  cat "$DB_FILE"    \
    | awk -F"," '
      BEGIN{ OFS="," }
      '"$PICKUP_COND"'{
        print '"${OUTPUT_ITEMS}"'
      }'
fi

$PICKUP_CONDにつてはまた次回。

さいごに

今回はここまで。

基本的にUnixコマンドは行指向で列の処理が苦手な印象だけど、awkは強い。

指定列だけ抜き出したり入れ替えたりする処理はよくありそうなので、
汎用的な列の抽出入れ替えコマンドを作っておくのもいいかもかも。

そんなawkは次回も大活躍。好ご期待。

確認環境

PC Thinkpad X1 Carbon 2nd Gen
OS FreeBSD 12.1-RELEASE-p4

参考