Powered by SmartDoc

2 `foo` は別なシェルなのだ

たとえばスクリプトの途中で処理時間を計測したいとき,

echo "Starting at `putime -s`"
・・・
echo "Ended at `putime -e` consumed `putime -i`"

などとしよう.ただし,putimeは以下のようなかんじとする.

putime()
{
    local __time_now __time_int __sec __min __hr

    __time_now=`env LANG=C date`
    case $1 in
    -e)
_time_end=`env LANG=C date -j -f "%a %b %d %T %Z %Y" "${__time_now}" "+%s"`
        echo ${__time_now}
        ;;
    -i)
        : $((__time_int = _time_end - _time_start))
        : $((__sec = __time_int % 60))
        : $((__min = __time_int / 60 % 60))
        : $((__hr  = __time_int / 60 / 60 % 60))
        printf "%02d:%02d:%02d\n" ${__hr} ${__min} ${__sec}
        ;;
    -s)
_time_start=`env LANG=C date -j -f "%a %b %d %T %Z %Y" "${__time_now}" \
    "+%s"`
        echo ${__time_now}
        ;;
    esac
}

しかしこれでは

% sh ./putime.sh
Starting at Thu May 14 10:47:49 JST 2015
..........done
Ended at Thu May 14 10:47:59 JST 2015 consumed 00:00:00
%

となってしまう.これはコマンド置換は基本的に別シェル(サブシェル)で行なわれるからだ.つまり.コマンド置換で実行したスクリプト内で定義した変数の値は全て保存されない.この場合,putime -sおよびputime -eで保存するつもりの_time_startおよび_time_endputime -i実行時には未定義となり結果は0となるわけだ.ということで,こういう場合にはちょっと手間はかかるがコマンド置換実行前に_time_startおよび_time_endを保存しておく必要がある.つまり

putime -s
echo "Starting at `putime`"
・・・
putime -e
echo "Ended at `putime` consumed `putime -i`"

とし,putime

putime()
{
    local __time_now __time_int __sec __min __hr

    __time_now=`env LANG=C date`
    case $1 in
    -e)
_time_end=`env LANG=C date -j -f "%a %b %d %T %Z %Y" "${__time_now}" "+%s"`
        ;;
    -i)
        : $((__time_int = _time_end - _time_start))
        : $((__sec = __time_int % 60))
        : $((__min = __time_int / 60 % 60))
        : $((__hr  = __time_int / 60 / 60 % 60))
        printf "%02d:%02d:%02d\n" ${__hr} ${__min} ${__sec}
        ;;
    -s)
_time_start=`env LANG=C date -j -f "%a %b %d %T %Z %Y" "${__time_now}" \
    "+%s"`
        ;;
    *)
        echo ${__time_now}
        ;;
    esac
}

とすればよい.