引用されたパラメータを渡すためにevalを使用する必要があるのはなぜですか?

引用されたパラメータを渡すためにevalを使用する必要があるのはなぜですか?

次の例があります。

#!/bin/bash
ARGUMENTS="-executors 1 -description \"The Host\" "

# call1
# error: parameter Host" is not allowed
java -jar swarm-client.jar $ARGUMENTS

# call2    
# works fine with eval
eval java -jar swarm-client.jar $ARGUMENTS

から$ARGUMENTS私は主張を引用します。引用の問題を解決するcall1理由を理解できません。eval

シェルのコマンド評価のプロセスと順序を理解していないようです。私に説明してもらえますか?

ベストアンサー1

あなたはしません引用された引数を渡すコマンドの場合、引数を渡すことができます。

入力するとき:

cmd arg1 arg2

シェルは、スペースが単語区切り文字である独自の構文で行を解析し、引数としてcmd1呼び出されます。cmdarg1arg2

ノート:cmd引数に空白文字を許可しません。スペースはシェル言語構文の演算子にすぎません。

Cと同様に、func("foo", "bar")実行時に2つのポインタ引数を受け取って作成した場合、または空白文字はfunc表示されません。(,"

シェル構文の一部も引用されます。"シェル構文の他の部分を含む文字を含むことができる単語に使用されます。

これを行うとき:

cmd "arg 1" arg2

cmdcmdarg 1およびarg2引数を受け取ります。何の文字も見えません"。これは"、シェル構文でスペースが単語区切り文字として扱われないようにするために使用されます。

今これを行う:

cmd $VAR

これは次のこととは異なります。

cmd the content of the variable

その場合、問題が発生します。

VAR='foo; reboot'
echo $VAR

例えば。

Bourne のようなシェルではの内容がどちら$VARにも単一引数で逐語的に渡されません (残念ながらこの問題は、およびそれより少ないcmd一部の他のシェルでは修正されました)。rc代わりに、分割とワイルドカード()が適用され、結果の単語がに渡されます。esfishzshsplit+globcmd

$IFS分割は、デフォルトではスペース、タブ、および改行を使用する特殊変数の文字に基づいています。

$ARGUMENTS含まれている内容については、、で-executors 1 -description "The Host"区切ります。これらの単語にはワイルドカードが含まれていないため、glob部分は適用されないため、これらの単語はに渡されます。-executors1-description"TheHost"cmd

ここでは、演算子を使用し、split+globその単語に表示されない文字を区切り文字として使用して部分を分割できます。

ARGUMENTS='-executors|1|-description|The Host'
IFS='|'
cmd $ARGUMENTS

または、これをサポートするシェル(例bash:)の場合はより良いです。配列の使用、これらのパラメータをすべて含む変数を含めることができます。

evalシェルコードを評価することです。したがって、別のオプションは、ARGUMENTSシェルコード(引数リストではなくシェル構文のテキスト)を含め、それをeval解釈に渡すことです。しかし、分割+グローブ演算子を避けるために変数を引用することを忘れないでください。

eval "cmd $ARGUMENTS"

おすすめ記事