個々のステップを測定するために使用するVagrantボックス用の設定スクリプトがありますtime
。ここで、条件付きで時間測定を有効または無効にしたいと思います。
たとえば、前の行は次のようになりました。
time (apt-get update > /tmp/last.log 2>&1)
これで、次のように簡単にできるようです。
MEASURE_TIME=true
[[ $MEASURE_TIME = true ]] && TIME="time --format=%e" || TIME=""
$TIME (apt-get update > /tmp/last.log 2>&1)
しかし、これはうまくいきません。
syntax error near unexpected token `apt-get'
`$TIME (apt-get update > /tmp/last.log 2>&1)'
ここで問題は何ですか?
答え1
行く能力がある時間必要なサブシェルtime
キーワード、コマンドではありません。
キーワードはtime
言語の一部であり、文字通り入力してコマンドの最初の単語として入力した場合にのみ認識されます(の場合、ksh93
次のトークンはで始まりません-
)。言うまでもなく、入力も"time"
機能しません(そしてコマンド呼び出し$TIME
として扱われます)。time
ここでは、別の解析ラウンドが実行される前に拡張されるエイリアスを使用できます(したがって、シェルにtime
キーワードを認識させる)。
shopt -s expand_aliases
alias time_or_not=
TIMEFORMAT=%E
MEASURE_TIME=true
[[ $MEASURE_TIME = true ]] && alias time_or_not=time
time_or_not (apt-get update > /tmp/last.log 2>&1)
これtime
キーワードオプションは-p
許可されません(除く)。ただし、書式設定に変数を使用できますbash
。 (この部分も具体的であり、通常は他のシェルには必要ありません。)TIMEFORMAT
bash
shopt
bash
答え2
これはalias
一つのアプローチですが、できるまた完了しました。コマンドを実行したくeval
ないのではなく、コマンドが欲しいものです。eval
eval
宣言。
私はalias
esが大好きです。常に使用しますが、関数を好む。特に、引数を処理する能力とalias
es のようにコマンド位置から拡張する必要がないという点です。
だから私はあなたもこれを試してみたいと思いました。
_time() if set -- "${IFS+IFS=\$2;}" "$IFS" "$@" && IFS='
'; then set -- "$1" "$2" "$*"; unset IFS
eval "$1 $TIME ${3#"$1"?"$2"?}"
fi
このビットは$IFS
主に。$*
( subshell bit )
また、シェル拡張の結果したがって、パラメータを解析可能な文字列に拡張するには"$*"
eval
"$@"
(しかし、すべての引数が空白で連結できると確信していない限り、これを実行しないでください)。 args in間の区切り文字は"$*"
の最初のバイトなので、$IFS
その値を確信せずに進めるのは危険です。したがって、関数はを保存し、入れるのに十分な長さのewline$IFS
に設定し、以前にその値があった場合はその値をリセットします。\n
set ... "$*"
"$3"
unset
以下は小さなデモです。
TIME='set -x; time'
_time \( 'echo "$(echo any number of subshells)"' \
'command -V time' \
'hash time' \
\) 'set +x'
ご存知のように、私は両方のコマンドを値に入れました$TIME
。どんな数でも可能です。なしでも同様です。ただし、引数と同様にエスケープされ、正しく引用されていることを確認してください_time()
。実行時にすべてコマンド文字列にリンクされますが、各引数には独自の\n
ewlineがあるため、比較的簡単に拡張できます。あるいは、必要に応じてそれらをすべてまとめて、行\n
番号やセミコロンなどで区切ることもできます。単一の引数が呼び出されたときにスクリプトの別の行に安全に入力できるコマンドを示すことを確認してください。\(
、例えば.が次に来る限り、大丈夫です\)
。これは基本的に一般的なものです。
eval
上記のコードを取得すると、次のようになります。
+ eval 'IFS=$2;set -x; time (
echo "$(echo any number of subshells)"
command -V time
hash time
)
set +x'
そして結果は次のとおりです。
出力
+++ echo any number of subshells
++ echo 'any number of subshells'
any number of subshells
++ command -V time
time is a shell keyword
++ hash time
bash: hash: time: not found
real 0m0.003s
user 0m0.000s
sys 0m0.000s
++ set +x
エラーは、私がインストールしていhash
ないことを示します。/usr/bin/time
(私はそうではないから)command
実行したら教えてください。末尾はset +x
実行される別のコマンドです。後ろに time
(これは可能です)- 操作を実行するときは、必ずコマンドを慎重に入力してくださいeval
。