評価セット( "$params")の代わりにbash配列を使用できますか?

評価セット( "$params")の代わりにbash配列を使用できますか?

見ています。optparseライブラリオプションの解析では、bash特に生成されたコードの次の点を参照してください。

params=""
while [ $# -ne 0 ]; do
  param="$1"
  shift

  case "$param" in

    --my-long-flag)
      params="$params -m";;
    --another-flag)
      params="$params -a";;
    "-?"|--help)
      usage
      exit 0;;
    *)
      if [[ "$param" == --* ]]; then
        echo -e "Unrecognized long option: $param"
        usage
        exit 1
      fi
      params="$params \"$param\"";;  ##### THIS LINE
  esac
done

eval set -- "$params"  ##### AND THIS LINE

# then a typical while getopts loop

ここで使用する本当の理由はありますかeval?入力eval 〜らしい適切な消毒を行います。しかし、次のものを使用することも同様に効果的ではないでしょうか?

params=()
# ...
    --my-long-flag)
      params+=("-m");;
    --another-flag)
      params+=("-a");;
# ...
      params+=("$param");;
# ...
set -- "${params[@]}"

私にとっては、これはよりきれいに見えます。

実際には、配列から直接(または?paramsを使用せずに)代わりにを使用してオプションを解析できますか?setwhile getopts "ma" option "${params[@]}"; dowhile getopts "ma" option; do

答え1

問題は「しなければならない評価セットの代わりにbash配列を使用する - "$params"? 「正解ははい!

スクリプト内のevalへの入力は明らかに次のようになります。いいえ正しく消毒してください。努力する

    yourscript '`xterm`'

バックティックが一重引用符で正しく囲まれていても、xtermが起動することがわかります。 (比較

    echo '`xterm`'

xtermは起動しません。 )

バグを保存しながら修正することはeval非常に困難です。行を変えても

    params="$params \"$param\"";;

到着

    params="$params '$param'";;

役に立たない: 今

    yourscript '`xterm`'

xtermはもう起動しませんが、

    yourscript \'' `xterm` '\'

まだ。

答え2

あなたはしません必要ここで配列を使用してくださいbash(しかし、より良い気分であれば使用してください)。

実行方法は次のとおりです/bin/sh

#!/bin/sh

for arg do
    shift

    case "$arg" in
        --my-long-flag)
            set -- "$@" -m ;;
        --another-flag)
            set -- "$@" -a ;;
        "-?"|--help)
            usage
            exit 0 ;;
        --*)
            printf 'Unrecognised long option: %s\n' "$arg" >$2
            usage
            exit 1 ;;
        *)
            set -- "$@" "$arg"
    esac
done

これはbash他の変数を導入する必要がないため、配列ソリューション(個人の意見)よりもきれいです。また、各コマンドライン引数は次のように保持されるため、表示される自動生成コードよりも優れています。別のプロジェクト存在する"$@"。これは、ユーザーが引用符で囲んだ空白文字を含むパラメータを渡すことができるため、これは良い方法です(自動生成されたコードはこれを実行しません)。


スタイルの説明:

  • 上記のループは、後で繰り返すために長いオプションを短いオプションに変換する必要がありますgetopts。だから実際に作業が中断されます。パフォーマンス-?などのいくつかのオプション--help。 IMHOは-h(または適切な短いオプション)に翻訳する必要があります。

  • 長いオプションも翻訳できますオプションを受け入れてはいけない点を超えました。。呼び出しスクリプトは次のとおりです。

    ./script.sh --my-long-flag -- -?
    

    しなければならない(「オプションはここで終わります」という意味)は-?オプションとして解釈されないからです。--同様に、

    ./script.sh filename --my-long-flag
    

    しなければならない--my-long-optionオプションの解析は最初の非オプションで停止する必要があるため、オプションとして解釈されません。

上記を考慮したバリエーションは次のとおりです。

#!/bin/sh

parse=YES

for arg do
    shift

    if [ "$parse" = YES ]; then
       case "$arg" in
            --my-long-flag)
                set -- "$@" -m ;;
            --another-flag)
                set -- "$@" -a ;;
            --help)
                set -- "$@" -h ;;
            --)
                parse=NO
                set -- "$@" -- ;;
            --*)
                printf 'Unrecognised long option: %s\n' "$arg" >$2
                usage
                exit 1 ;;
            *)
                parse=NO
                set -- "$@" "$arg"
        esac
     else
        set -- "$@" "$arg"
     fi

done

これは何のためであるか。いいえ長いオプションを許可分離--option hellohelloオプションではなく処理され、オプションの解析が終了します)などのオプション引数です。--option=helloただし、いくつかの追加の修正により、このような操作を簡単に処理できます。

関連情報