AtCoder の AtCoder Beginners Selection、転職活動していた時に解いた問題の数々を思い出す感じで楽しいです。
とはいえ、当時は C で解いていたのに、今は第一候補は Bash でその次が PHP、そのあとにやっと C。変わるもんだ。
Beginners Selection の問題は (その他もそうかもしれないけれど) 標準入力からテストケースをインプットし、想定のロジックに従った標準出力をするという形で作られています。今回解いた Shift only は、本来ならもっとスマートな方法がありそうなのですが、かなり力技で解きました。
その中で、標準入力からスペース区切りで受け取った内容を配列に格納したかったのですが、その時にやり方を調べたのでメモ。
標準出力から読み込む
読み込むには read
が使えます。
1 つの値を読み込む
よくこんな形で使われているかと思います。
#!/bin/bash -u
echo "Continue? [y/N] > "
read answer # ここで読み込み待ち
if [ "${answer}" != "y" ]; then
echo "Aborted."
exit 1
fi
echo "Continuing..."
# 以降処理を続ける
exit 0
$ bash ./read.sh
Continue? [y/N] > y
Continuing...
$ echo $?
0
$
$ bash ./read.sh
Continue? [y/N] > N
Aborted.
$ echo $?
1
複数の値を読み込む
入力される値がわかっていれば (固定なら) こんな感じにできます。
#!/bin/bash -u
echo "Input three values > "
read a b c
echo ${a}
echo ${b}
echo ${c}
exit 0
$ bash read2.sh
Input three values > 7 30 365
7
30
365
このやり方を知る前
Qiita のいろいろな記事から学んだのでどれと言えないのですが、このやり方を知る前は普通にまとめて 1 個の文字列として読んだ後、awk で分割していました。
#!/bin/bash -u
echo "Input three values > "
read line
a=$(( echo "${line}" | awk -F' ' '{ print $1 }' ))
b=$(( echo "${line}" | awk -F' ' '{ print $2 }' ))
c=$(( echo "${line}" | awk -F' ' '{ print $3 }' ))
echo ${a}
echo ${b}
echo ${c}
exit 0
入力個数がわからない場合はどうしたら?
以下のようにすると配列に読み込める
#!/bin/bash -u
echo "Input values > "
declare -a array=()
echo "Continue? [y/N] > "
read array # ここで読み込み待ち
for number in ${array[@]}; do
echo ${number}
done
$ bash read_array.sh
Input values > 1 2 3 4 5
1
2
3
4
5
Conclusion
PHP では特に対話的なコンソールアプリを作る機会があまりないので、こういう問題タイプだとついつい Bash を選びますが、まだまだ知らないことがたくさんあるなあと発見ばかりでした。