プロが教えるわが家の防犯対策術!

exprで四則演算をする際に変数を動的にした場合の記述法について

#!/bin/bash

DATA60=`date +%-H%M%S`
Old_DATA=$DATA60
jikan=`expr $DATA60 - $Old_DATA`
echo "DATA60 $DATA60"
echo "Old_DATA60 $Old_DATA"
echo "jikan $jikan"
echo " "

DATA60=`date +%-H%M%S`
Name=(red yellow blue)
for i in ${Name[@]}
do
eval "${i}_DATA"=`date +%-H%M%S`
eval "echo ${i}_DATA \$${i}_DATA"
eval 'jikan=`expr \$${i}_DATA - $DATA60`'
echo $jikan
sleep 2
done

上記を実行すると、
$ . test-expr.sh
DATA60 170553
Old_DATA60 170553
jikan 0

red_DATA 170553
expr: 整数でない引数

yellow_DATA 170555
expr: 整数でない引数

blue_DATA 170557
expr: 整数でない引数

と、エラーになってしまいます。
経過時間をそれぞれ知りたいのですが、exprで四則演算をする際に変数を動的にした場合、どのように記述すれば良いか、お教えねがえませんでしょうか

A 回答 (3件)

>どうしてシングルクォーテーションで囲まなければいけないのかの理由がよくわからないのですが、



囲んだわけじゃなくて、外に出したわけですね。シングルクォートの中では変数展開されないので。

eval 'jikan=`expr \$'${i}'_DATA - $DATA60`'

jikan=`expr \$' までは1つのシングルクォートの中で、'_DATA - $DATA60`' が2つめのシングルクォートの中。${i} はシングルクォートの外。

そもそも、bashなら配列を使えば良いのでは?Nameのところで使ってるわけだし。

DATA60=`date +%-H%M%S`
Name=(red yellow blue)
for i in ${Name[@]}
do
DATA[$i]=`date +%-H%M%S`
echo DATA[$i] ${DATA[$i]}
jikan=`expr ${DATA[$i]} - $DATA60`
echo $jikan
sleep 2
done

時分秒表現を引き算しても意味のある数字になりませんが、いいのでしょうか?
date +%s がいいのでは?
    • good
    • 0
この回答へのお礼

アドバイスいただきありがとうございます。

・シングルクォートの件
基本的な事だと思うんですが、分からない自分にとっては目から鱗です。

「外に出す」というので、なるほど~!と納得です。

シングルクォートの範囲が外側同士じゃなくて、中に入れたシングルクォートに境界が移り、間にあるバッククォートは単なる文字列でしかなくなるという解釈なんですね。そして外に出た変数が展開される・・・と。

納得です~。

後、ご指摘の配列を使えば良いのでは?
という事ですが、まさしくおっしゃるとおりです^^;
何年プログラムやってるんだ~って感じですねw
発想力が乏しいというか、応用が効かないというか・・まだまだだな~と実感させられてしまいます。う~ん恥ずかしい限りですw

更に、data +%sのご指摘も 単に経過秒数だけをカウントするという事じゃ駄目な事に気が付きました。

dataコマンドのオプション調べてたんですけど、視点が1日単位。という発想が何とも間抜けですね。
sleepを24時間2秒後でテストしたとしても、カウントは2ですもんね。

色々鋭いご指摘を頂き、また一つ大きくなれた気がします 感謝です ありがとうございました!

お礼日時:2013/11/27 09:51

一応、解決はしたみたいですが


> 何度も見なおして
というところが気になったので。

bash の -x オプションはご存知でしょうか?

もしご存知なければ、マニュアルで調べてください。
デバグがかなり楽になります。
    • good
    • 0
この回答へのお礼

バッシュのデバッグ どうやるんだろう・・と思いつつ検索せずじまいでした。

なるほどですね~。

通常のエラー箇所で止まるのと違い、実行処理が1行ずつ表示されてとても良いですね^^

感謝です ありがとうございます!

お礼日時:2013/11/27 09:53

eval してるところ,


どんな文字列を eval してるのか
はちゃんと確認できてる?
    • good
    • 0
この回答へのお礼

ご助言ありがとうございます。
何度も見なおしてeval箇所を下記の形で実現できました。

eval 'jikan=`expr \$'${i}'_DATA - $DATA60`'

バッククォート内でシングルクォーテーションで\$'${i}'_DATA のようにする事で展開できました!

ですが、どうしてこれで展開できるのかの理由が良くわからないです。

一番外側をシングルクォーテーションで囲い、バッククオートでexprコマンドを実行する際、その中にあるシングルクォートで囲った${i}が展開されるてうまくいきましたが、ここをダブルクォテーションで囲むと、「expr: 整数でない引数」のエラーになってしまいます。

どうしてシングルクォーテーションで囲まなければいけないのかの理由がよくわからないのですが、もしお分かりになるようでしたら、お教え願いませんでしょうか

お礼日時:2013/11/26 19:17

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!