グローバルマッチでランダムなアイテムを返す

グローバルマッチでランダムなアイテムを返す

とともにグローバル予選zshファイル名ワイルドカードパターンの一致結果は、さまざまな方法でソートできます。たとえば、このパターンは、*(om)変更タイムスタンプに基づいて現在のディレクトリに隠されていないすべての名前と一致します。

しかし、時には方法があったらいいのにランダム化ソート(ファイルのランダムなサンプルを取得するなど)私が知っている限り、これを直接実行する修飾子はありません。

zshQ:ファイル名グロービングパターンから任意のパス名のリストを取得するには?

答え1

任意のソートキー(グローバル予選 oe)::

*(Noe\''REPLY=$RANDOM,$RANDOM'\')

説明する:

  • oeその後、単一文字の区切り記号、コード、その他の区切り文字が続きます。コードブロックに区切り文字を含めることはできません。グローバル修飾子自体を解析するときは、特殊文字が解析されないように特殊文字をエスケープする必要があります。
  • 私は'区切り文字として使用し(エスケープが必要なのでバックスラッシュを使用)、'存在できる特殊文字を保護するためにコードをラップします。これを行うと'
  • 一致するファイル名ごとに、コードブロックが順番に実行されます。
  • REPLY最初はファイル名に設定され、コードで設定されたすべてがREPLYソートキーとして使用されます。

$n要素をランダムにサンプリングするには、[…]修飾子を追加します。

*(Noe\''REPLY=$RANDOM,$RANDOM'\'[1,$n])

いくつかの要素が同じソートキーを持っているので、すべての置換の可能性は同じではなく、ソート機能をディレクトリの順序でリストに適用した結果を保存することに少し偏りがありますが、偏向は小さいです。私はこれを$RANDOM,$RANDOMソートキーとして使用していますが、$RANDOMバイアスを減らすためのものではありません。$RANDOM15桁の数字でファイル数が2^15に近いほど偏りが目立つようになります。

$RANDOMわずかな偏りが問題にならない場合は、サンプリングに十分です。セキュリティに関連するものには適していません。安全なランダム置換を望む場合は、GNU coreutilsを使用してください。shuf。 (お気に入りのオペレーティングシステムに基本機能が不足していshufて何らかの理由でGNU coreutilsをインストールしたくない場合は、次のことを試すことができます。イーサラの悟り代わりに。 )

securely_permuted=("${(0)$(printf '%s\0' *(N) | shuf -z))}")

あるいは、より単純なバージョンはコマンドラインの長さ制限に達することができます。

securely_permuted=("${(0)$(shuf -z -- *(N)))}")

1実験的に、順序は安定していますが(たとえば*(omoe\''REPLY=1'\')同じ*(om))、順序は*(oe\''REPLY=1'\')一致しません*(oN)。それにもかかわらず、これはいくつかの特定の順序で有利な小さな偏差である。

関連情報