変数に格納したコマンドを実行する場合 - Linux シェルスクリプト プログラミング
PROGRAM
変数に格納したコマンドを実行する場合
Linux シェル (sh) で、変数の値として、実行したいコマンドを文字列で格納して、それを実行しようとしたときに、なかなか上手く行かずに苦労してしまったことがありました。
その上手くいかなかった場合というのは、$COMMAND という変数に、文字列としてコマンドと引数を併せて指定していて、その引数の中に "xxx yyy" というような空白を挟むものがあった時に発生しました。
# このような実行方法では、空白が含まれる引数があると、そこで次の引数とされてしまう様子です。
${COMMAND}
このような感じの場合、引用符で括った引数があると、引数に余計な引用符がついたり、ひとつの引数内の空白部分で 2 つの引数として分割されてしまうなどの、動作不良が発生するようでした。
実際にどのような動きになっているかは "/bin/sh -x" で実行して確認してみたところ、例えば、次のようなスクリプトを実行した場合は、次のような処理の流れになっていました。
# -m オプションで "METHOD ADDED" という空白入りの引数を指定しています。
COMMAND="git commit -m \"METHOD ADDED\""
# この時に次のように実行すると、
# 実際には git commit -m '"METHOD' 'ADDED"' というコマンドが実行されようとするようでした。
${COMMAND}
どうやら引用符で括っていても、それらが別々の引数であると判断してしまい、また、二重引用符が含まれた引数を丁寧に単引用符で括ってくれるため、完全にそれぞれが別の引数として認識されてしまうようでした。
これは、変数から直接ではなく "eval" コマンドを使用することで、簡単に回避することができました。
# -m オプションで "METHOD ADDED" という空白入りの引数を指定しています。
COMMAND="git commit -m \"METHOD ADDED\""
# eval で実行することで、
# 実際には eval 'git commit -m "METHOD ADDED"' というコマンドが実行されるようでした。
eval ${COMMAND}
このように "eval" コマンドで実行すると、$COMMAND 変数に格納した値は、まるごとひとつで "eval" の引数として認識されるため、引数の区切りや引用符などを自動的に調整されずに、期待通りにコマンドを実行することができました。
この感じから、変数に格納したコマンドを実行する際には、冒頭に "eval" を付けることを忘れないようにするのが良さそうですね。
[ もどる ]