2016-08-09 6 views
2

У меня есть Regexrule.cs класса, он состоит из следующих свойств:Замена Regex строки в C#

public string Expression { get; set; } 
    public string FirstOpen { get; set; } 
    public string FirstClose { get; set; } 
    public string SecondOpen { get; set; } 
    public string SecondClose { get; set; } 

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

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

FirstOpen + Group[1] + FirstClose и SecondOpen + Group[2] + SecondClose

Во всяком случае, у меня есть List<RegexRule> Rules; который содержит список RegexRules объектов.

затруднительного

Моя цель состоит в том, чтобы петли через каждый один один тех (RegexRules r), запустить его соответствующее выражение (r.Expression) на особенно длинной строки, и, когда эти две ожидаемые группы нашел, я хочу, чтобы сценарий инкапсулировать каждую группу с ее префиксов и суффиксов так, как показано ... опять же,

r.FirstOpen + Group[1] + r.FirstClose и r.SecondOpen + Group[2] + r.SecondClose

Я пробовал много разных способов, но одна вещь, которую я знаю, это то, что str.Replace не будет работать, в цикле. Поскольку он будет применять префиксы и суффиксы снова и снова, для каждого появления результатов выражения.

Так как же еще это можно достичь?

спасибо.

Редактировать

Это то, что я в настоящее время есть:

foreach (RegexRule r in RegexRules.ToList()) 
{ 
    Regex rx = new Regex(r.Expression); 
    MatchCollection mc = rx.Matches(str); 
    foreach (Match m in mc) 
    { 
     MessageBox.Show("replacing"); 
     str = str.Replace(m.Groups[1].Value, r.OpenBBOne + m.Groups[1].Value + r.CloseBBOne); 
    } 
} 

Edit 2 - Специфические

Пользователи смогут создавать свои собственные Regex конфигурации в .config, и он будет в таком формате:

reg {(\w+).(\w+)\(\);} = [("prefix1","suffix1"),("prefix2","suffix2")];


reg - Стандартное слово для определения нового RegexRule
{ {(\w+).(\w+)\(\); } - Их регулярное выражение (условие: выражение должно всегда возвращать 2 группы в своих матчах)
[("prefix1","suffix1"),("prefix2","suffix2")] - Два параметра в `[(» », ""), ("", "")] - которые представляют префиксы и суффиксы для двух групп

** Пример **

Если мы применили выше конфигурацию этой строки:

Lorem ipsum foo.bar(); dolor sit bar.foo(); amit consecteteur...

Регулярное выражение будет захватывать foo.bar() как матч, в этом foo спичка [1] группа [1], и bar спичка [1] группа [2], согласно регулярному выражению.

То же самое касается bar.foo(), потому что bar спички [2] группы [1], и foo матча [2] группа [2]

Я надеюсь, что это имеет смысл ...

+2

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

+0

@JeremyHolovacs Я не знаю ... как еще это можно сделать? –

+0

@BarryD, предположим, у вас есть '([0-9]). ([A-z])' как регулярное выражение и '1aa1' в качестве входной строки. Вы хотите, чтобы оба * '1' были заменены или только первый (т. Е. Один соответствовал регулярному выражению)? –

ответ

1

В соответствии с нашим обсуждение, я думаю, это может быть решением для вас. Это связано с первым замечанием, которое я сделал. Он дает вам уникальные значения для вашего MatchCollection с использованием .Distinct(), чтобы вы не закончили составление префиксов и суффиксов.

foreach(RegexRule r in RegexRules.ToList()) 
{ 
    Regex rx = new Regex(r.Expression); 
    MatchCollection mc = rx.Matches(str); 
    foreach(Match m in mc.OfType<Match>().Distinct()) 
    { 
     MessageBox.Show("replacing"); 
     str = str.Replace(m.Groups[1].Value, 
          r.OpenBBOne + m.Groups[1].Value + r.CloseBBOne); 
    } 
} 

Если вы не можете использовать LINQ для какой-то причине, вы всегда можете просто в принципе сделать то же самое самостоятельно, создав новый List<Match> и только добавив в те, которые еще не в списке.

foreach(RegexRule r in RegexRules.ToList()) 
{ 
    Regex rx = new Regex(r.Expression); 
    MatchCollection mc = rx.Matches(str); 

    List<Match> matches = new List<Match>(); 
    List<string> strings = new List<string>(); 
    foreach(Match m in mc) 
     if(!strings.Contains(m.Value)) 
     { 
      matches.Add(m); 
      strings.Add(m.Value); 
     } 

    foreach(Match m in matches) 
    { 
     MessageBox.Show("replacing"); 
     str = str.Replace(m.Groups[1].Value, 
          r.OpenBBOne + m.Groups[1].Value + r.CloseBBOne); 
    } 
} 
+0

Это было не только трудно объяснить, но я действительно не смог пройти мимо него, и вы представили единственное решение, которое у меня есть, без исключения. И это сработало. Большое спасибо, сэр!! Но: 'mc.Distinct();' не будет работать, потому что это 'MatchCollection', спасибо за альтернативу :) –

+0

Ах, да, вы правы. Я забыл, что вам нужно определить тип, чтобы вы могли получить перечислитель. Я отредактировал свой ответ, чтобы он работал с LINQ. – Meloviz

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