Сопоставьте строку с простым рисунком

#c# #regex #string #pattern-matching

#c# #регулярное выражение #строка #сопоставление с шаблоном

Вопрос:

Я пытаюсь проверить программу, которую я создаю, на будущее, чтобы шаблон, который мне нужен для ввода пользователями, не был жестко закодирован. Всегда есть вероятность, что скороговорка с буквами или цифрами может измениться, но когда это произойдет, мне нужно, чтобы все оставались последовательными. Кроме того, я хочу, чтобы менеджеры контролировали то, что поступает, не полагаясь на меня. Возможно ли использовать регулярное выражение или другой инструмент для сравнения ввода со списком, хранящимся в базе данных. Я хочу, чтобы это было легко, чтобы шаблоны, хранящиеся в базе данных, выглядели как X ###### или X ######-X ######## и так далее.

Комментарии:

1. Вероятно, вы можете использовать маски (своего рода регулярные выражения) вместо реальных регулярных выражений: см. msdn.microsoft.com/en-us/library/… Их можно использовать в текстовых полях, чтобы пользователи могли вводить только правильный текст.

2. Это форма WPF или Win? Пожалуйста, добавьте больше деталей к вашему требованию. Rgds,

Ответ №1:

Конечно, просто сохраните правила регулярных выражений в столбце string в таблице, а затем загрузите их в IEnumerable<Regex> в вашем приложении. Тогда совпадение — это просто совпадение ЛЮБОГО из этих правил. Имейте в виду, что конфликтующие правила могут быть склонны к жадной гонке (выигрывает первое, которое будет проверено), поэтому вам нужно быть осторожным. Также имейте в виду, что существует множество оптимизаций, которые вы могли бы выполнить помимо моего примера, который разработан так, чтобы быть простым.

 List<string> regexStrings = db.GetRegexStrings();
var result = new List<Regex>(regexStrings.Count);
foreach (var regexString in regexStrings)
{
    result.Add(new Regex(regexString);
}

...

// The check
bool matched = result.Any(i => i.IsMatch(testInput));
  

Комментарии:

1. Этот пример действительно работает, но как мне заставить его работать более динамично. Возвращается значение true, если входные данные имеют значение X # ##, а база данных имеет значение X ###. Однако я хочу, чтобы X # ## было истинным для X123, но ложным для X1234. Этот тип сравнения.

2. Кроме того, я надеялся, что база данных действительно будет содержать «X # # #». Я знаю, что в Excel вы можете создавать пользовательские поля, подобные этому

3. Вы бы использовали ограничения регулярных выражений… Существуют способы ограничить входные данные для сопоставления. Вам нужно будет немного поискать в Google, чтобы узнать о способах ограничения ввода регулярных выражений.

Ответ №2:

Вы могли бы сохранить свои шаблоны как есть в своей базе данных, а затем преобразовать их в регулярные выражения.

Я не знаю конкретно, какие символы вам понадобятся в вашем формате, но давайте предположим, что вы просто хотите заменить число на # и оставить остальное как есть, вот некоторый код для этого:

 public static Regex ConvertToRegex(string pattern)
{
    var sb = new StringBuilder();

    sb.Append("^");

    foreach (var c in pattern)
    {
        switch (c)
        {
            case '#':
                sb.Append(@"d");
                break;

            default:
                sb.Append(Regex.Escape(c.ToString()));
                break;
        }
    }

    sb.Append("$");

    return new Regex(sb.ToString());
}
  

Вы также можете использовать такие параметры, как RegexOptions.IgnoreCase если это то, что вам нужно.

ПРИМЕЧАНИЕ: По какой-то причине Regex.Escape экранирует # символ, даже если он не является особенным… Поэтому я просто выбрал посимвольный подход.

Ответ №3:

         private bool TestMethod()
{
    const string textPattern = "X###";
    string text = textBox1.Text;
    bool match = true;

    if (text.Length == textPattern.Length)
    {
        char[] chrStr = text.ToCharArray();
        char[] chrPattern = textPattern.ToCharArray();
        int length = text.Length;

        for (int i = 0; i < length; i  )
        {
            if (chrPattern[i] != '#')
            {
                if (chrPattern[i] != chrStr[i])
                {
                    return false;
                }
            }
        }
    }
    else
    {
        return false;
    }
    return match;
}
  

Это делает все, что мне нужно сейчас. Тем не менее, спасибо за все советы. В будущем мне придется подробнее изучить регулярное выражение.

Ответ №4:

Используя MaskedTextProvider , вы могли бы сделать что-то вроде этого:

 using System.Globalization;
using System.ComponentModel;
  
 string pattern = "Xamp;amp;amp;amp;amp;amp;-Xamp;amp;amp;amp;amp;amp;amp;";
string text = "Xabcdef-Xasdfghi";

var culture = CultureInfo.GetCultureInfo("sv-SE");
var matcher = new MaskedTextProvider(pattern, culture);
int position;
MaskedTextResultHint hint;
if (!matcher.Set(text, out position, out hint))
{
    Console.WriteLine("Error at {0}: {1}", position, hint);
}
else if (!matcher.MaskCompleted)
{
    Console.WriteLine("Not enough characters");
}
else if (matcher.ToString() != text)
{
    Console.WriteLine("Missing literals");
}
else
{
    Console.WriteLine("OK");
}
  

Описание формата см.:http://msdn.microsoft.com/en-us/library/system.windows.forms.maskedtextbox.mask