1

スクリプトを次のように呼び出したい:

./script -f "-a -b "foo bar"" baz

スクリプトによって内部的に実行される-a -b "foo bar"コマンド (例: ) に渡すコマンド ライン引数はどこにありますか。grep

ここでの問題は、もちろん引用に関係しています。素朴なアプローチ (コマンドライン引数を に展開する) は、 とを別々の引数としてscript扱いますが、これはもちろん望ましくありません。foobar

これを達成するための最良の方法は何ですか?

4

2 に答える 2

4

それを達成するための本当に優れた方法はありません。回避策しかありません。ほとんどすべての一般的な解決策では、個々の引数を個々の引数として渡す必要があります。これは、引数のリストを単一の引数として渡すという代替案では、少し複雑な引数 (あなたの例は、あなたが陥ろうとしているメタクォートの泥沼の始まりにすぎません. 詳細については、この Bash FAQ エントリを参照してください)。

おそらく最も一般的な解決策は、パススルーする引数を引数リストの最後に置くことです。これは、実際にスクリプト用の引数の末尾を知る必要があることを意味します。これは多かれ少なかれ、固定数の位置パラメーターがあることを意味します。通常、固定数は 1 です。この戦略の例は、スクリプトの名前を 1 つの位置引数として受け取るスクリプト インタープリター (bashそれ自体、など) です。pythonそれはあなたの呼び出しになります:

./script baz -a -b "foo bar"

それは必ずしも便利ではありません。findたとえば、コマンドにはオプション-execがあり、その後に続く引数で実際のコマンドが続きます。そのためには、通過する単語がどこで終わるかを知る必要があります。find特定の区切り文字引数、つまり単一のセミコロンを使用して解決します。(これは任意の選択でしたが、スクリプトの引数としては非常にまれであるため、通常はうまくいきます。) その場合、呼び出しは次のようになります。

./script -f -a -b "foo bar" \; baz

明らかに、引用符で囲む;必要があります。そうしないと、コマンドが終了してしまうからです。しかし、それは複雑な引用符の問題ではありません。

これは、ユーザーが区切り文字を明示的に指定できるようにすることで拡張できます。

./script --arguments=--end -a -b "foo bar" --end baz

find-like 提案のサンプル コードを次に示します。

# Use an array to accumulate the arguments to be passed through
declare -a passthrough=()

while getopts f:xyz opt; do
  case "$opt" in
    f)
       passthrough+=("$OPTARG")
       while [[ ${!OPTIND} != ';' ]]; do
         if ((OPTIND > $#)); then
           echo "Unterminated -f argument" >>/dev/stderr
           exit 1
         fi
         passthrough+=("${!OPTIND}")
         ((++OPTIND))
       done
       ((++OPTIND))
     ;;
    # Handle other options
  esac
done
# Handle positional arguments

# Use the passthrough arguments
grep "${passthrough[@]}" # Other grep arguments
于 2015-12-19T06:06:56.520 に答える