変数に格納したコマンドを実行する場合 - 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" を付けることを忘れないようにするのが良さそうですね。


[ もどる ]