web-dev-qa-db-ja.com

ワイルドカードを使用した文字列の一致

文字列をワイルドカード(*)と一致させたいのですが、ワイルドカードは「任意」を意味します。例えば:

*X = string must end with X
X* = string must start with X
*X* = string must contain X

また、次のようないくつかの複合的な用途:

*X*YZ* = string contains X and contains YZ
X*YZ*P = string starts with X, contains YZ and ends with P.

これを行う簡単なアルゴリズムはありますか?正規表現を使用するかどうかはわかりません(可能性はありますが)。

明確にするために、ユーザーは上記の内容をフィルターボックス(できるだけ単純なフィルター)に入力します。ユーザー自身が正規表現を記述する必要はありません。したがって、上記の表記法から簡単に変換できるものがあればよいでしょう。

50
Robinson

参考までに、couldVB.NETを使用してください Like-Operator

string text = "x is not the same as X and yz not the same as YZ";
bool contains = LikeOperator.LikeString(text,"*X*YZ*", Microsoft.VisualBasic.CompareMethod.Binary);  

大文字小文字を無視する場合は、CompareMethod.Textを使用します。

using Microsoft.VisualBasic.CompilerServices;を追加する必要があります。

22
Tim Schmelter

多くの場合、ワイルドカードはtwoタイプのジョーカーで動作します:

  ? - any character  (one and only one)
  * - any characters (zero or more)

したがって、これらのルールを適切なregular expressionに簡単に変換できます。

  // If you want to implement both "*" and "?"
  private static String WildCardToRegular(String value) {
    return "^" + Regex.Escape(value).Replace("\\?", ".").Replace("\\*", ".*") + "$"; 
  }

  // If you want to implement "*" only
  private static String WildCardToRegular(String value) {
    return "^" + Regex.Escape(value).Replace("\\*", ".*") + "$"; 
  }

そして、通常通りRegexを使用できます:

  String test = "Some Data X";

  Boolean endsWithEx = Regex.IsMatch(test, WildCardToRegular("*X"));
  Boolean startsWithS = Regex.IsMatch(test, WildCardToRegular("S*"));
  Boolean containsD = Regex.IsMatch(test, WildCardToRegular("*D*"));

  // Starts with S, ends with X, contains "me" and "a" (in that order) 
  Boolean complex = Regex.IsMatch(test, WildCardToRegular("S*me*a*X"));
106
Dmitry Bychenko

WildcardPattern from System.Management.Automationを使用することもできます。

pattern = new WildcardPattern(patternString);
pattern.IsMatch(stringToMatch);

Visual Studio UIでは、プロジェクトの参照にSystem.Management.Automationアセンブリを追加できない場合があります。 here の説明に従って、手動で追加してください。

15
VirtualVDX

*X*YZ* = string contains X and contains YZ

@".*X.*YZ"

X*YZ*P = string starts with X, contains YZ and ends with P.

@"^X.*YZ.*P$"
4
Avinash Raj

ワイルドカード*は、.*または.*?正規表現パターンとして変換できます。

改行記号と一致させるために単一行モードを使用する必要がある場合があります。この場合、(?s)を正規表現パターンの一部として使用できます。

パターン全体または一部に設定できます:

X* = > @"X(?s:.*)"
*X = > @"(?s:.*)X"
*X* = > @"(?s).*X.*"
*X*YZ* = > @"(?s).*X.*YZ.*"
X*YZ*P = > @"(?s:X.*YZ.*P)"
4

Y *との一致をチェックするとき、Regex IsMatchがXYZでtrueになることを考慮する必要があります。それを避けるために、「^」アンカーを使用します

isMatch(str1, "^" + str2.Replace("*", ".*?"));  

したがって、問題を解決するための完全なコードは

    bool isMatchStr(string str1, string str2)
    {
        string s1 = str1.Replace("*", ".*?");
        string s2 = str2.Replace("*", ".*?");
        bool r1 = Regex.IsMatch(s1, "^" + s2);
        bool r2 = Regex.IsMatch(s2, "^" + s1);
        return r1 || r2;
    }
3
Pavel Khrapkin