ファイル名が中括弧で拡張されたglobパターンセットの1つと一致するかどうかをプログラムでどのように確認できますか?

ファイル名が中括弧で拡張されたglobパターンセットの1つと一致するかどうかをプログラムでどのように確認できますか?

$string文字列がグローバルパターンと一致するかどうかを知りたいです$pattern$string既存のファイルの名前であってもなくてもよい。どうすればいいですか?

私の入力文字列が次の形式であるとしましょう。

string="/foo/bar"
pattern1="/foo/*"
pattern2="/foo/{bar,baz}"

$stringbashイディオムが一致するか、他の任意のグローバルパターンと一致するかどうかを確認します。これまでに試したことは次のとおりです。$pattern1$pattern2

  1. [[ "$string" = $pattern ]]

    $patternグローバルパターンではなく文字列パターンとして解釈されることを除いて、ほとんど機能します。

  2. [ "$string" = $pattern ]

    このアプローチの問題は、文字列が拡張された後と$pattern拡張の間で文字列比較が実行されることです。$string$pattern

  3. [[ "$(find $pattern -print0 -maxdepth 0 2>/dev/null)" =~ "$string" ]]

    この方法は機能しますが、$stringファイルが存在する場合にのみ可能です。

  4. [[ $string =~ $pattern ]]

    =~演算子は$patternグローバルまたはワイルドカードパターンではなく拡張正規表現として解釈されるため、これは機能しません。

ベストアンサー1

この問題に対する普遍的な解決策はありません。その理由は、bashで中括弧拡張(別名{pattern1,pattern2,...}およびファイル名拡張(別名globパターン))が別々に扱われ、異なる条件と時間に拡張されるためです。以下は、bashで実行される拡張の完全なリストです。

  • 支柱の拡張
  • チルダ拡張
  • パラメータと変数の拡張
  • コマンドの置き換え
  • 算術拡張
  • 噴射
  • パス名拡張

これらのサブセット(おそらく中括弧、チルダ、パス名の拡張)にのみ興味があるため、特定のパターンとメカニズムを使用して制御可能な方法で拡張を制限できます。たとえば、

#!/bin/bash
set -f

string=/foo/bar

for pattern in /foo/{*,foo*,bar*,**,**/*}; do
    [[ $string == $pattern ]] && echo "$pattern matches $string"
done

このスクリプトを実行すると、次の出力が生成されます。

/foo/* matches /foo/bar
/foo/bar* matches /foo/bar
/foo/** matches /foo/bar

これはset -f、パス名拡張が無効になっているため、ステートメントで中括弧拡張とチルダ拡張のみが発生するために機能しますfor pattern in /foo/{*,foo*,bar*,**,**/*}。その後、中[[ $string == $pattern ]]かっこ拡張を実行した後、テスト操作を使用してパス名拡張をテストできます。

おすすめ記事