Соответствие строк с помощью шаблона

Я хотел бы сопоставить строки с подстановочным знаком (*), где подстановочный знак означает "any". Например:

*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.

Есть ли простой алгоритм для этого? Я не уверен в использовании регулярных выражений (хотя это и есть возможность).

Чтобы уточнить, пользователи будут вводить приведенное выше в поле фильтра (как можно более простой фильтр), я не хочу, чтобы им приходилось самостоятельно писать регулярные выражения. Так что я могу легко преобразовать из вышеупомянутых обозначений, было бы хорошо.

Ответ 1

Просто FYI, вы можете использовать VB.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;.

Ответ 2

Часто дикие карты работают с двумя типами джокеров:

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

чтобы вы могли легко преобразовать эти правила в соответствующее регулярное выражение:

  // 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"));

Ответ 3

Использование WildcardPattern из System.Management.Automation может быть вариантом.

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

Пользовательский интерфейс Visual Studio может не позволить вам добавить сборку System.Management.Automation к ссылкам вашего проекта. Не стесняйтесь добавлять его вручную, как описано здесь.

Ответ 4

*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$"

Ответ 5

Подстановочный знак * может быть переведен как .* или .*? шаблон регулярного выражения.

Возможно, вам понадобится использовать режим одиночной линии для соответствия символам новой строки, и в этом случае вы можете использовать (?s) как часть шаблона регулярного выражения.

Вы можете установить его для всего или части шаблона:

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

Ответ 6

Необходимо учитывать, что Regex IsMatch дает true с XYZ, проверяя совпадение с Y *. Чтобы избежать этого, я использую якорь <^ >

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;
    }

Ответ 7

Пример приложения консоли С#

Пример командной строки:
C:/" > App_Exe -Opy PythonFile.py 1 2 3
Консольный выход:
Список аргументов: -Opy PythonFile.py 1 2 3
Найденное имя файла python: PythonFile.py

using System;
using System.Text.RegularExpressions;           //Regex

namespace ConsoleApp1
{
    class Program
    {
        static void Main(string[] args)
        {
            string cmdLine = String.Join(" ", args);

            bool bFileExtFlag = false;
            int argIndex = 0;
            Regex regex;
            foreach (string s in args)
            {
                //Search for the 1st occurrence of the "*.py" pattern
                regex = new Regex(@"(?s:.*)\056py", RegexOptions.IgnoreCase);
                bFileExtFlag = regex.IsMatch(s);
                if (bFileExtFlag == true)
                    break;
                argIndex++;
            };

            Console.WriteLine("Argument list: " + cmdLine);
            if (bFileExtFlag == true)
                Console.WriteLine("Found python filename: " + args[argIndex]);
            else
                Console.WriteLine("Python file with extension <.py> not found!");
        }


    }
}