2014-02-02 2 views
1

Для выбора пользователя я хотел бы предоставить список чисел, соответствующих заданному регулярному выражению. Само регулярное выражение очень просто он только может выглядеть следующим образом 123 [0-9] [0-9] или [4-9] 34,2Сгенерировать все совпадения для regex

я узнал, что Fare (https://github.com/moodmosaic/Fare) делает работа как-то. следующий пример:

string pattern = "123[0-9][0-9]"; 
var xeger = new Xeger(pattern); 
var match = xeger.Generate(); //match is e.g. "12349" 

К сожалению Fare Пб только дает мне один возможный матч, но не все 100 возможных комбинаций строка может иметь.

Если вы думаете, что регулярное выражение не является хорошей идеей в этом случае и скорее предложит реализацию for-loop, которая заменяет символы, я также собираюсь с этим, но в настоящее время я не знаю, как это сделать? Может быть, рекурсивная функция была бы умной?

+0

Что можно ожидать от '[0-9] +' –

+0

извините, не уверен, что вы имеете в виду 123 [0-9] [0-9] дает 12300, 12310,12311 и т. Д. – Kai

+0

Но '[0-9] +' производит ** бесконечные ** результаты. Если вы знаете шаблон и если он * ограничен *, как в вашем примере, вам не нужно регулярное выражение. Вложенных двух циклов достаточно для for (int i = 0; i <10; i ++) {for (int j = 0; j <10; j ++) {}} '. –

ответ

1

Я предпочел бы создать свою собственную реализацию, чем использовать библиотеку. Следующий код делает то, что вы хотите достичь.

private static Regex regexRegex = new Regex("\\[(?<From>\\d)-(?<To>\\d)]", RegexOptions.Compiled); 

    private static IEnumerable<string> GetStringsForRegex(string pattern) 
    { 
     var strings = Enumerable.Repeat("", 1); 
     var lastIndex = 0; 
     foreach (Match m in regexRegex.Matches(pattern)) 
     { 
      if (m.Index > lastIndex) 
      { 
       var capturedLastIndex = lastIndex; 
       strings = strings.Select(s => s + pattern.Substring(capturedLastIndex, m.Index - capturedLastIndex)); 
      } 
      int from = int.Parse(m.Groups["From"].Value); 
      int to = int.Parse(m.Groups["To"].Value); 
      if (from > to) 
      { 
       throw new InvalidOperationException(); 
      } 
      strings = strings.SelectMany(s => Enumerable.Range(from, to - from + 1), (s, i) => s + i.ToString()); 
      lastIndex = m.Index + m.Length; 
     } 
     if (lastIndex < pattern.Length) 
     { 
      var capturedLastIndex = lastIndex; 
      strings = strings.Select(s => s + pattern.Substring(capturedLastIndex)); 
     } 
     return strings; 
    } 

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

Опасайтесь переменной capturedLastIndex. Это необходимо, поскольку компилятор в противном случае захватывал бы переменную lastIndex, что приводило бы к неправильным результатам.

+0

Извините, не работает для' GetStringsForRegex (@ "1 \ d3 [0-9] [0-9]") ' –

+0

извините, но, к сожалению, не работает либо для шаблона = "1234". ни для "1234 [0-9]" – Kai

+0

@ L.B Ум, вы изначально писали: «это может быть только 123 [0-9] [0-9] или [4-9] 34.2". Не упоминается '\ d'. (И вы можете добавить поддержку '.', обрабатывая' .' так же, как '[0-9]'.) –

0

Это мой код, который теперь работает для меня. не очень общий характер и только два возможных выражения в строке, но она работает;)

 List<string> possibleMatches = new List<string>(); 

     string expression = "123?[3-9]" //this is an example 

     if (expression.Contains("?") || expression.Contains("[")) 
     {    
      int count = expression.Count(f => f == '?'); 
      count += expression.Count(f => f == '['); 
      if (count <= 2) 
      { 
       string pattern = expression.Replace('*', '.').Replace('?', '.'); 
       pattern = pattern.Replace(".", "[0-9]"); 

       int pos1 = pattern.IndexOf('['); 
       int start1 = Convert.ToInt32(pattern[pos1 + 1].ToString()); 
       int end1 = Convert.ToInt32(pattern[pos1 + 3].ToString()); 

       int pos2 = 0; 
       int start2, end2 = 0; 
       if (count > 1) 
       { 
        pos2 = pattern.IndexOf('[', pos1); 
        start2 = Convert.ToInt32(pattern[pos2 + 1].ToString()); 
        end2 = Convert.ToInt32(pattern[pos2 + 3].ToString()); 

        pattern = pattern.Remove(pos1, "[0-9]".Length); 
        pattern = pattern.Remove(pos2, "[0-9]".Length); 

        string copy = pattern; 
        for (int i = start1; i <= end1; i++) 
        { 
         copy = pattern.Insert(pos1, i.ToString()); 
         for (int y = start2; y <= end2; y++) 
         { 
          possibleMatches.Add(copy.Insert(pos2, y.ToString())); 
         } 
        } 
       } 
       else 
       { 
        pattern = pattern.Remove(pos1, "[0-9]".Length); 

        for (int i = start1; i <= end1; i++) 
        { 
         possibleMatches.Add(pattern.Insert(pos1, i.ToString())); 
        } 
       } 
      } 
Смежные вопросы