Exercismの簡単な問題に詰まってなかなか解決できなかったのでメモ。
問題
最初に書いたコード
#!/usr/bin/env bash
total() {
total=$(echo "2^64 - 1" | bc)
echo $total
}
exponential() {
result=$(echo "2^($1 - 1)" | bc)
echo $result
}
main() {
if (( $1 == "total" )); then
echo $(total)
elif (( ($1 > 0) && ($1 < 65) )); then
echo $(exponential $1)
else
echo "Error: invalid input" >&2
return 1
fi
}
main "$@"
これだと一つだけ、エラーが出る。
✗ square 0 raises an exception
(from function `assert_failure' in file bats-extra.bash, line 190,
in test file grains.bats, line 58)
`assert_failure' failed
-- command succeeded, but it was expected to fail --
output : 18446744073709551615
--
テストの内容は
@test "square 0 raises an exception" {
run bash grains.sh 0
assert_failure
assert_output "Error: invalid input"
}
grains.shに0を渡したらエラーが出るはずなのに、出ていない。どうやらtotal()が呼ばれてしまっている。
なんで?
原因
(( $1 == "total" ))
が$1が0のときにtrueと判定されてしまっていた。これはなぜかというと(( )) は算術評価であって、文字列評価ではないから。(())の中では文字列は0とされてしまい、通ってしまっていた。
正しくは
[[ $1 == "total" ]]
学んだこと
算術評価は(( )) 、文字列評価は[[ ]] の中に書く!!