Rso's Jotter

日々の開発の知見のメモやその他雑記

3分間シェル芸クッキング: 締切まで 後X営業日です をターミナル起動時に表示する

ふと実装したくなったプチ処理をシェルでサクッと実施するメモしておきます。

本日は, ちょっと先の期日の締切(プロジェクト完了日とか上期終了日など) まで何営業日あるんだろう、それを 毎日表示することができたら便利かも?と思ったので、それをシェルでサクッと作ったらどうなるかをご紹介しようと思います。

仕様としては以下の通りです。

  • 指定した期日まで、本日から数えて後何営業日(土日祝除く) をターミナル起動時に表示する。
  • 指定した期日は頻繁に変更にされる想定ではないので、ハードコードしても良いとする。

また仕様ではないですが、

  • 出来るだけサクッと作成できる方法を選択する

として、上記を作ってみようと思います。

まず祝日の判定ですが、RubyやJSなど使えば祝日判定ライブラリがあるのですが、それらをインストールしたり、日付から祝日かどうかを毎回判定するもの処理が大変なので、今年の祝日リストをサクッとExcelなどで作ります。祝日は内閣府のページ などを参照して引っ張ってきます。 今回は 日付,曜日,祝日かどうか をCSVに書きました。

作成したCSVは、以下のような内容になります。

.calendar.csv · GitHub

上記のファイルをダウンロードして, .calendar.csv としてホームディレクトリに保存します。

これで下準備は完了で、いよいよシェルによる調理を行います。 色々やり方はあり、 sedawk でももちろんできるのですが、これらに馴染みのない人には謎文字列の羅列に見えがちという欠点がありますので、今回は皆さまに馴染みのある grep を使うパターンでやりたいと思います。

で、早速ですが実際のシェルを以下に示します。 締め切りは 上半期の終わり (2019-06-30) を入れています。自分は .zshrc に記載していますが、 bashの人は .bashrc に記載すれば大丈夫です。

today=`date +%Y-%m-%d`
eigyo_bi=`grep ${today} -A 1000 .calendar.csv | grep -B 1000 "2019-06-30" | grep -v "[土日祝]" | wc -l | tr -d " "`
echo "##########################"
echo "今期の営業日はあと ${eigyo_bi}日です"
echo "##########################"

これだけで終わりです。設定した後にシェルを立ち上げると以下のような表示がされると思います。

f:id:rso:20190225221609p:plain

以上です! が、ちょっとだけ処理の内容を説明しておきます。

today=date +%Y-%m-%d

これは シェル変数today に本日の日付を所定のフォーマットにして格納しています。 例えば本日の投稿日 で在れば "2019-02-25" という文字列が入ります。

grep ${today} -A 1000 .calendar.csv

これは .calendar.csv の 本日の日付以降1000行を表示しています。 grep -A -1 でも似たような挙動になるようなのですが、ドキュメントに載っていなかったので、適当に1000行としています。

grep -B 1000 "2019-06-30"

さらに、締切の期日 "2019-06-30" 以前の1000行を表示します。これで本日 ~ 締切までの日付一覧が抜粋されている状態となります。

grep -v "[土日祝]"

さらに、土日祝 の文字列のいずれかにマッチした行を省いています -v は grep でマッチしていない行のみ出力するオプションで、頻出です。

wc -l | tr -d " "

最後に残った行数をカウントしてやれば、営業日の数となります。wc -l は先頭にスペースが含まれた状態で出力されるので、 tr -d " " で不要なスペースを除いて、完成です。

とまあざっくりですがこんな感じです。毎回ログイン時に表示されるのは良くないとか、カレンダーを毎年作らないといけないとか、締め切りがハードコードなのは 如何なものか.. というのはもちろんありますが、とりあえずやりたいと思った処理を 10分ぐらいで作れた(ほとんど CSV作成) のでまあこんなもんかなと思います。

もっとこうしたらカッコよくできる、みたいなのがありましたらブログ、Twitterなどでご紹介ください。