2019年01月12日 に更新

シェルスクリプトで暗記カードを作った話

⚠️ この記事は最終更新日から3年以上が経過しています。

突然ですが Jan. や Feb. といった月名の略称を見たときにそれが何月かスムーズに思い出せますか?

思い出せる人はとてもえらいです。ちなみに私はさっき Jun. という文字を見て何月か思い出すことが出来ずショックを受けました。June ってなんだか6月感が薄いと思うんですよね。どうしようもない話ですみません…。

何とかするためシェルスクリプトでサクッと暗記マシーン(?)を作ることにしました。

動いてるところ

ランダムに問題を出題し、答えるだけのシンプルなツールです。

simple-tester-sample

CTRL-C キーなどでスクリプトを終了するまで無限に出題され続けるスパルタ仕様になっています。何度かやって無事に覚えることができました🙆

ソースコード

なるべくシェル芸感は薄めて、前に書いた シェルスクリプトを高級言語のような書き味に近づける Tips 集 の内容を取り入れた実装にしています。

#!/usr/bin/env bash
set -Ceuo pipefail

# 出題する問題集を定義
# スペース区切りで問題とその回答を記述しておく
readonly QUESTIONS=$(
  cat <<FIN
Jan 1
Feb 2
Mar 3
Apr 4
May 5
Jun 6
Jul 7
Aug 8
Sep 9
Oct 10
Nov 11
Dec 12
FIN
)

# 色付きの echo 関数
function cecho() {
  local color_name color
  readonly color_name="$1"
  shift
  case $color_name in
    red) color=31 ;;
    green) color=32 ;;
    yellow) color=33 ;;
    *) color=30 ;;
  esac
  printf "\033[${color}m%b\033[m\n" "$*"
}

# 標準入力で渡された全行の中から
# ランダムに一行を取り出すフィルタ関数
function rand_line() {
  cat - | perl -MList::Util=shuffle -E 'say shuffle(<STDIN>);'
}

# 標準入力で渡された一問を出題する関数
function ask_question() {
  # 区切り文字を半角スペースでスプリットし、
  # $question と $answer に代入する
  IFS=" " read -r question answer

  # 出題文を表示する
  echo "[Q] $question"

  # 回答の入力待ちをする
  read -rp "[A] " input </dev/tty

  # 入力された回答を答え合わせ
  if [[ $input == "$answer" ]]; then
    cecho green "正解"
  else
    cecho red "不正解  (正解は「${answer}」でした)"
  fi
  echo
}

# ランダムに一問を出題する関数
function ask_any_question() {
  # 問題集を出力する
  echo "$QUESTIONS" |
    # 全問題の中からランダムに一問を取得する
    rand_line |
    # 取得した一問を出題する
    ask_question
}

function main() {
  echo "表示される月の略称が何月か回答してください!"
  echo

  # 出題を繰り返すメインループ
  while true; do
    ask_any_question
  done
}

main

回答の入力待ちは無くしてランダムに出題と回答表示を繰り返すだけのほうが暗記カードっぽくなるかもしれませんね。

月名に限らず、問題集の定義を書き換えれば英単語の単語カードなどでも使えるとおもいます。出来れば問題データは別ファイルに定義した方がいいですが今回は省略したいとおもいます。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

計算問題(認証) *