4

問題

スクリプトに指定されたパラメーターをそのまま使用したいと思います-引用符とすべてを使用します。これまでのところ、私が見つけたすべての解決策は引用符を取り除くか、微妙に異なることをします。

シナリオ

たとえば、コマンドラインパラメータとして文字列を受け入れるツールがあります

./tool --formula="AG EF phi;"

さらに、スクリプトを呼び出すラッパースクリプトがあります。その呼び出しは

wrap.sh ./tool --formula="AG EF phi;"

このスクリプトは次のようなことをします

# preparation phase
# ...

# call tool and remember exit code
$*
result=$?

# evaluation phase
# ...

exit $result

残念ながら、ツールは次のように呼ばれます

./tool --formula=AG EF phi;

これは上記と同じではなく、構文エラーが発生します。私が見つけた唯一のハックは私に次のようなものを与えるでしょう

./tool "--formula=AG EF phi;"

これも間違っています。

詳細

具体的には、問題を例示するためのダミーコードを次に示します。

まず、Cプログラム「tool.c」。

#include <stdio.h>

int main(int argc, char** argv) {
    int i;
    for (i = 0; i < argc; i++) {
        printf("%d: %s\n", i, argv[i]);
    }
    return 0;
}

次に、ラップスクリプト「wrap.sh」:

#!/bin/bash
echo $*
$*
exit $?

これが私が試したことです:

$ ./tool --formula="Foo bar"
0: ./tool
1: --formula=Foo bar

$ ./wrap.sh ./tool --formula="Foo bar"
./tool --formula=Foo bar
0: ./tool
1: --formula=Foo
2: bar

$ ./wrap.sh ./tool --formula="\"Foo bar\""
./tool --formula="Foo bar"
0: ./tool
1: --formula="Foo
2: bar"

$ ./wrap.sh ./tool --formula="\"Foo bar\""
./tool --formula="Foo bar"
0: ./tool
1: --formula="Foo
2: bar"

$ ./wrap.sh "./tool --formula=\"\\\"Foo bar\\\"\""
./tool --formula="\"Foo bar\""
0: ./tool
1: --formula="\"Foo
2: bar\""

そして、これが私が欲しいものです(ラップスクリプトの必要な変更のために):

$ ./wrap.sh ./tool --formula="Foo bar"
0: ./tool
1: --formula=Foo bar

提案

引用符をエスケープ

Shabazが提案したように引用符をエスケープすると、変数$*には正しく引用符で囲まれた文字列が含まれます。たとえば、次のようになります。

wrap.sh ./tool --formula="\"AG EF phi;\""

そしてwrap.shコードで:

echo $*

を生成します

./tool --formula="AG EF phi;"

ただし、実行$*すると、上記のように正確なエラーが発生します。の引数はformula「AG」の後に削除されます。さらに、引用符をエスケープしないと便利です。

別のシェルが役立ちますか?

4

3 に答える 3

4

BashFAQ / 050を参照してください(「コマンドを変数に入れようとしていますが、複雑なケースは常に失敗します!」)。

空白を保持し、引数の受け渡しを適切に処理するには、これを使用してラッパースクリプトへの引数を実行する必要があります。

"$@"

この方法では、ラッパーを実行するときに余分な引用符を作成する必要はありません。

$ cat ./wrap.sh
#!/bin/bash
echo "$@"
"$@"
result=$?
exit $result
$ ./wrap.sh ./tool --formula="Foo bar"
./tool --formula=Foo bar
0: ./tool
1: --formula=Foo bar

引用符を使用しない、引用符を付けない$@、または$*引用符を$*付けると、文字列が平坦化され、必要なグループ化が失われた一連の単語として表示されます。

差出人man bash

   *      Expands  to  the positional parameters, starting from one.  When
          the expansion occurs within double quotes, it expands to a  sin‐
          gle word with the value of each parameter separated by the first
          character of the IFS special variable.  That is, "$*" is equiva‐
          lent to "$1c$2c...", where c is the first character of the value
          of the IFS variable.  If IFS is unset, the parameters are  sepa‐
          rated  by  spaces.   If  IFS  is null, the parameters are joined
          without intervening separators.
   @      Expands to the positional parameters, starting from  one.   When
          the  expansion  occurs  within  double  quotes,  each  parameter
          expands to a separate word.  That is, "$@" is equivalent to "$1"
          "$2"  ...   If the double-quoted expansion occurs within a word,
          the expansion of the first parameter is joined with  the  begin‐
          ning  part  of  the original word, and the expansion of the last
          parameter is joined with the last part  of  the  original  word.
          When  there  are no positional parameters, "$@" and $@ expand to
          nothing (i.e., they are removed).
于 2012-06-07T11:16:53.757 に答える
2

必要な空白を保持するために機能するこのスクリプトを使用できます。

#!/bin/bash
exec bash -c "$*"
ret=$?
exit $ret

次のコマンドラインを使用して、上記のスクリプトを実行します。

./wrap.sh ./tool --formula="\"Foo bar baz\""

出力:

0: ./tool
1: --formula=Foo bar baz
于 2012-06-07T11:21:47.483 に答える
1

で脱出する必要が"あり\ます。ただし、それらを1つの文字列に保持するには、それらを再びで囲む必要があり"ます。あれは:

./tool --formula="\"AG EF phi;\""

"text"Bashは、スペースが含まれている場合でも、すべてをtext1つの単語として自動的に変換します。それは他の非特別なキャラクターのようにエスケープされたキャラクターを脅かします。したがって、実際に文字"を書くには、を使用する必要があります\"。2つのポイントの組み合わせ("スペースで区切られた単語を1つの単語として保持し、"それ自体を入力する必要があるため)は、上記の行になりました。

ここで、スクリプトにこの行を実行させたいと思いますが、bash自体のパラメーターとしてスクリプトに渡します。したがって、この分析と特殊文字の置換/削除は2回行われます。したがって、この分析後に上記の行が生成されるように、パラメーターをスクリプトに渡す必要があります。したがって:

./wrap.sh "./tool --formula=\"\\\"AG EF phi;\\\"\""

"すべてが現在どのように変換され\"、すべてが\に変換されているかに注意してください\\。すべてが引用符で囲まれています。

PSこれはechoでテストできます。

$ echo "a b c"
a b c
$ echo "\"a b c\""
"a b c"
$ echo "echo \"\\\"a b c\\\"\""
echo "\"a b c\""
于 2012-06-07T09:43:41.837 に答える