読者です 読者をやめる 読者になる 読者になる

カイワレの大冒険 Third

技術的なことや他愛もないことをたまに書いてます

シェルスクリプトで浮動小数点演算したら、怒られたので、晒しとく

単にデータ取ってきて演算するだけだろとか思い、気楽に作ろうとしたら、認識あまーと諭されたので、書いてみる。
※今回使ったシェルはボーンシェルです。

まずは、ファイルに書かれたデータを単に出力(cat)するシェルスクリプト。

#!/bin/sh
COUNT_FILE=/home/user/work/count
COUNT=`cat $COUNT_FILE`
echo $COUNT

まぁ、これはよいでしょう。 次も簡単。

#!/bin/sh
COUNT_FILE=/home/user/work/count
COUNT=`cat $COUNT_FILE`

MAX_FILE=/home/user/work/max
MAX=`cat $MAX_FILE`

echo $COUNT
echo $MAX

そして、これもよいでしょう。やってることは同じです。同じことを2ファイルでやっただけ。

問題はここで演算させたときだった!

まず、演算ということで、気軽に足し算を。
「/home/user/work/count」には15、「/home/user/work/max」には33が書かれている?(表現むずい)とする。

#!/bin/sh
COUNT_FILE=/home/user/work/count
COUNT=`cat $COUNT_FILE`

MAX_FILE=/home/user/work/max
MAX=`cat $MAX_FILE`

echo $COUNT
echo $MAX

TASU=`expr $COUNT + $MAX`
echo $TASU

まぁ、こんな感じでやれば、

15
33
48

と出力してくれたので、どんな演算も楽だろうと思ってました僕…

魅惑の除算

まさか割ると結果違うなんて… ということで、書き換えてみましょう。

#!/bin/sh
COUNT_FILE=/home/user/work/count
COUNT=`cat $COUNT_FILE`

MAX_FILE=/home/user/work/max
MAX=`cat $MAX_FILE`

echo $COUNT
echo $MAX

WARU=`expr $COUNT / $MAX`
echo $WARU


WARU2=`expr $MAX / $COUNT`
echo $WARU2
結果:
15
33
0
2

0とか2とか整数で見事に叩き出してくれるわけですよ。僕は%とか割合出したいから、このあと100かけて、それで適当にifでも書いておけばよいんじゃねぐらいの感覚で書き始めたのに、見事に斜め上を行く反応を見せてくれたわけです。シェルスクリプト。

まぁ、僕が勉強不足で起きたことというか、単なる普通の挙動なのに、僕がテンパってただけなのですが、これは気軽に何とかしたいと。
んで、echoをパイプでbcに渡すという方法はあるのですが、なんか他にないかなぁと思案。

ありましたawk。見つけましたawk。

正直、awkが最適解かは分かりません。でも好きなコマンドを使いたいと思い、周りに迷惑かけるかもしれないけど、使いたくなってしまった…んで、awkでできるならそれでいこうと思い、結果的に書いたのが以下のスクリプト。

#!/bin/sh
COUNT_FILE=/home/user/work/count
COUNT=`cat $COUNT_FILE`
MAX_FILE=/home/user/work/max
MAX=`cat $MAX_FILE`

RATE=`echo $COUNT $MAX | awk '{printf ("%2d",$1/$2*100)}'`
echo RATE

$COUNTと$MAXをawkに渡して、printfで桁操作というかフィールド幅の調整を行なって、100かけて、それを出力という形。awkはこういう演処理ができるので、それに任せました。

まぁ、シェルでも以下のようなコマンド打ってみると分かるかと思います。他のシェルはまだ試してないので、良かったら試してみてくだされ!

echo 2 3 | awk '{printf ("%2d",$1/$2*100)}'
//これは66

echo 2 3 | awk '{printf ("%f",$1/$2)}'
//これは0.666667

この書き方は「個人的には」読みやすいし、フォーマットの指定もできるので、とりあえずはこれで回避しています。

終わりに

シェルスクリプトってわりとこのコマンドを実行とか、ファイル作成とかそういうことばっかりやってて、こんなことすら全然気づきませんでした。やっぱやらないと気づかないもんなんだなぁ。

まぁ、やって覚えてやって覚えて、そうやって知識としていくのがよいんでしょうけど、忘れたら意味ないので、備忘録も含めて書いておきます。わりと知られてることなのかなぁ。周知の事実というか、よく知られたことだったらすいませんw