61228
お世話になります。  
C#での文字列検索を行いたいと考えています。  
下記のようなリストを想定しています。

```

    List<string> file_list = new List<string>();
    file_list.Add("data/test01.txt");
    file_list.Add("data/test02.txt");
    file_list("data/test03.dat");
    file_list.Add("data/test04.dat");
    
```

とりあえず、FindAll等で文字列を指定して検索できることはわかったんですが、ファイル名のワイルドカード（「data/*.txt」のようなもの）にマッチする要素を取り出すにはどうしたらいいでしょうか。  
ちなみに、マッチする要素1つだけではなく、マッチするすべての要素を取得したいと考えています。  
何かアドバイスをいただけると幸いです。

以上、よろしくお願いいたします。
CC BY-SA 4.0
2019-12-07T13:25:47.163
61222
2019-12-08T04:51:38.343
29034
question
c#
C#のリストでの文字列検索について
コメントで紹介した３つのうち、最初の記事は色々と変なので忘れてください。

3つ目の英語版StackOverflowの記事が短くて良さそうです。  
[ Need to perform Wildcard (*,?, etc) search on a string using
Regex](https://stackoverflow.com/q/6907720/9014308)  
さらにオリジナルはこちらのようですが。  
[Converting Wildcards to
Regexes](https://www.codeproject.com/Articles/11556/Converting-Wildcards-to-
Regexes)

コピーしておくと：

>
```

>     public static string WildcardToRegex(string pattern)
>     {
>         return "^" + Regex.Escape(pattern)
>                           .Replace(@"\*", ".*")
>                           .Replace(@"\?", ".")
>                    + "$";
>     }
>  
```

上記を使って`FindAll()`のパラメータにすれば、こんな風に出来ます。

```

    // 検索パターンの正規表現を作成
    Regex RegexWild = new Regex(WildcardToRegex("data/*.txt"), RegexOptions.IgnoreCase);
    
    // 文字列のリストで取得
    List<string> ListResult = file_list.FindAll(s => RegexWild.IsMatch(s));
    
    // 文字列の配列で取得
    string[] ArrayResult = file_list.FindAll(s => RegexWild.IsMatch(s)).ToArray();
    
```

* * *

**追記**  
取り敢えずパス＆ファイル指定時との互換性を高めたものを作ってみました。  
突っ込みどころは色々あるでしょうが、今のところはこれまで。  
ただ、それらを考えるとコメントで紹介した最初の記事は、それなりに合理的だったのかもしれません。

```

    // ワイルドカードを使用したパスから正規表現へ
    // From Path with Wildcard To Regex
    public static string PathWildcardToRegex(string pattern)
    {
        string work = "^" + Regex.Escape(pattern)
                          .Replace(@"\*", ".*")
                          .Replace(@"\?", ".")
                   + "$";
        work = Regex.Replace(work, @"(\\\\|/)", @"[\\/]"); // 区切り記号に'/'と'\'の両方を許す
        work = work.Replace(@".*\..*", @".*");             // '*.*'は'*'に変える
        work = work.Replace(@".*\.[\\/]", @"[^.]+[\\/]");  // Path途中の'*.'の処理
        work = work.Replace(@".*\.$", @"[^.]+$");          // Path最後の'*.'の処理
        return work;
    }
    
```
CC BY-SA 4.0
2019-12-07T23:39:44.313
61228
2019-12-08T04:51:38.343
2019-12-08T04:51:38.343
26370
26370
61222
answer