パラメータを解析するための評価セットの使用を避けるには?

パラメータを解析するための評価セットの使用を避けるには?

パラメータ分析を勉強するとき強く打つスクリプトの使い方選択項目のインポート、私はほとんどどこでもこの構造が使用されるのを見ました: eval set -- "$SOMETHING_PARSED"。例えば、ここそしてここ。今後は作業スクリプトを無料で公開する予定なので、ユーザーにそのような空白を残したくありません。これを避ける方法はありますか?

説明するここバージョンによって異なります選択項目のインポート、使用する必要はありませんeval。しかし、少なくとも私の場合はそうではありません。選択項目のインポート次の文字列が与えられた場合、. ' -j --version= '\''1'\'' --number= '\''2'\'' -- '\''2C_IA/GBCs_out/nohope_2C_IA_off. xml'\'''&setはそれを正確に割り当てます$1

答え1

getopt非伝統的な方法で実装される、util-linuxまたは少なくとも非伝統的な方法で使用される全体的なポイントbusyboxは、評価するシェルコードを出力することです。シェル構文の特殊文字は実際にはオプション引数 1 で引用されるため、getopt² を除いて Bourne と同様のシェルで使用しても安全です。yash

POSIXsh言語では、コマンドがランダムな文字列のリストをシェルに返す最も簡単な方法です。

getoptこの作業モードをサポートしていない実装(getopt分割+グローブ演算子の使用に依存する元の実装)は、ランダムなリストを返すことができないため、意図的に破損しています。

eval何らかの理由で使用したくないがzsh切り替えるオプションがある場合は、次のものを使用できます。

argv=( "${(@XQ)${(z)$(getopt...)}}" ) || exit

パラメータ拡張フラグは、シェルの引用構文(引用構文ですが、単一引用符のみを使用して引用)にz基づいて表示され、引用符を削除し、構文エラーが発生すると文句を言います。zshgetoptQX

唯一の利点は、getopt邪悪なコードを出力する邪悪な命令に置き換えられても実行されないことです。邪悪な奴交換中ですgetopt。取る方が良いかもしれません。走る評価できるように出力するのではなく、邪悪なコード自体です。

NUL で区切られたコマンドを送信する場合は、出力を配列に読み込んで任意の文字列リストをbash4.4+ に渡すことができます。sh

readarray -td '' array < <(cmd) || exit # readarray failed.
wait "$!" || exit # cmd failed
set -- "${array[@]}"

または次のようになりますzsh

argv=( "${(0@)$(cmd)}" ) || exit
argv[-1]=() # remove the empty trailing argument caused by the terminating NUL

getoptしたがって、理論的には、この動作モードを使用してメソッドを実装することが可能です。

このgetoptユーティリティは、出力を評価することが期待される唯一のユーティリティではありません。以下も参照してください。

eval "$(dbus-launch --sh-syntax)"
eval "$(dpkg-architecture -u)"
eval "set $(git rev-parse --sq --prefix "$prefix" -- "$@")"
eval "$(lesspipe)"
eval "$(xz --robot --version)"
eval "$(resize)"
eval "$(dircolors)"

シェルの環境を変更するために使用されます。

現在の状態を保存して後で復元するために使用できるすべての項目も参照してください。

aliases=$(alias -L) # zsh
aliases=$(alias -p) # ksh/bash
options=$(set +o)
locale=$(locale)

元に戻すとeval "$aliases"...eval "$options"

getopt使用された解析オプションを含まない代替方法は次のとおりですeval

  • 標準getoptsの組み込み機能(ksh93³を除く)は単一文字オプションのみをサポートします。
  • zshzparseoptsキューブ
  • 私のものgetopts_longPOSIXsh関数

¹オプション名にはありませんが、少なくともバージョン2.38ではバグと見なすことができます。スクリプトオプションに愚かな名前を選択しない限り、大丈夫でしょう。

²現在のバージョンyash(2022年6月現在)は有効なテキストのみを処理できるため、現在のロケールからテキストにデコードできない引数はブロックされます。

³ksh93getoptsまたはzshはzparseoptsGNU(または)と同じ方法でオプションを解析しません。特に、短縮された長いオプションはサポートされていません。getopt_long()util-linux getopt

関連情報