2014-12-27 5 views
1

Мне нужно запустить соответствие C# RegEx в строке. Проблема в том, что я ищу несколько шаблонов для одной строки, и я не могу найти способ сделать это с помощью одного прогона.Запуск нескольких шаблонов RegEx для одной строки

Например, в строке

The dog has jumped 

Я ищу «собака» и «собака».

Я не знаю, как я могу получить эти два результата за один проход.

Я попытался объединить шаблон с символом переделки (|), как это:

(dog|dog has) 

Но он вернулся только первый матч.

Что я могу использовать для возврата обоих матчей?

Спасибо!

ответ

1

Механизм регулярных выражений вернет первую подстроку, удовлетворяющую шаблону. Если вы напишете (dog|dog has), он никогда не сможет соответствовать dog has, потому что dog has начинается с dog, что является первой альтернативой. Кроме того, механизм регулярных выражений не будет возвращать совпадающие совпадения.

Вот запутанным метод:

var patterns = new[] { "dog", "dog has" }; 

var sb = new StringBuilder(); 
for (var i = 0; i < patterns.Length; i++) 
    sb.Append(@"(?=(?<p").Append(i).Append(">").Append(patterns[i]).Append("))?"); 

var regex = new Regex(sb.ToString(), RegexOptions.Compiled); 
Console.WriteLine("Pattern: {0}", regex); 

var input = "a dog has been seen with another dog"; 
Console.WriteLine("Input: {0}", input); 

foreach (var match in regex.Matches(input).Cast<Match>()) 
{ 
    for (var i = 0; i < patterns.Length; i++) 
    { 
     var group = match.Groups["p" + i]; 
     if (!group.Success) 
      continue; 

     Console.WriteLine("Matched pattern #{0}: '{1}' at index {2}", i, group.Value, group.Index); 
    } 
} 

Это производит следующий вывод:

Pattern: (?=(?<p0>dog))?(?=(?<p1>dog has))? 
Input: a dog has been seen with another dog 
Matched pattern #0: 'dog' at index 2 
Matched pattern #1: 'dog has' at index 2 
Matched pattern #0: 'dog' at index 33 

Да, это злоупотребление регулярных выражений :)

Это работает путем создания шаблон с использованием дополнительных lookaheads, которые фиксируют подстроки как побочный эффект, но шаблон в противном случае всегда соответствует пустой строке. Итак, есть n+1 совпадений, n - длина ввода. Шаблоны не могут содержать пронумерованные обратные ссылки, но вместо этого вы можете использовать именованные обратные ссылки.

Кроме того, это может возвращать совпадающие совпадения, поскольку оно будет пытаться сопоставить все шаблоны во всех строковых позициях.

Но вы определенно должны сравнить это с ручным подходом (зацикливание на шаблоны и сопоставление каждого из них отдельно). Я не ожидаю, что это будет быстро ...

+0

Правда, но на основании вышеприведенного примера можно было предположить что если собака соответствует, то собака также соответствует как автоматическое логическое предположение. –

+0

@ Риос, да, ты прав. Я неправильно понял проблему. Я обновил ответ. –

+0

Ничего себе, это одно из решений ... Удивительно! Благодарю. – ml123

0

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

шаблон: (собака \ Ь имеет \ б) | (собака \ б)

я понял, этот шаблон с помощью онлайн-строитель здесь: enter link description here

Затем вы можете использовать его в C# с регулярным выражением класс, сделав что-то вроде

Regex reg = new Regex("(dog\b has\b)|(dog\b)", RegexOptions.IgnoreCase); 
if (reg.IsMatch){ 
    //found dog or dog has 
} 
+0

Пробовал, но это не сработало.Мне нужно, чтобы при использовании метода совпадений (а не IsMatch) я вернусь к двум совпадениям, один для «собаки» и один для «собаки». – ml123

Смежные вопросы