Определение того, какой шаблон соответствует, используя Regex.Matches - PullRequest
5 голосов
/ 24 июня 2010

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

Я использую словарь, в котором в качестве ключей используется список регулярных выражений, а значение словаряList<string>, который содержит дополнительный список значений замены.Если я собираюсь сделать это таким образом, чтобы понять, что заменитель, мне, очевидно, нужно знать, в чем ключ, как я могу определить, какой шаблон вызвал совпадение?

        var dictionary = new Dictionary<string, List<string>>
        {                     
            {"(?!e)ight", new List<string>(){"ite"}},
            {"(?!ues)tion", new List<string>(){"shun"}},
            {"(?:god|allah|buddah?|diety)", new List<string>(){"ceiling cat"}},
            ..
        }

        var regex = "(" + String.Join(")|(", dictionary.Keys.ToArray()) + ")";

        foreach (Match metamatch in Regex.Matches(input
           , regex
           , RegexOptions.IgnoreCase | RegexOptions.ExplicitCapture))
        {
            substitute = GetRandomReplacement(dictionary[ ????? ]);
            input = input.Replace(metamatch.Value, substitute);
        }

Возможно ли то, что я пытаюсь сделать, или есть лучший способ достичь этого безумия?

Ответы [ 3 ]

6 голосов
/ 24 июня 2010

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

Например, используя регулярное выражение ниже,

(?<Group1>(?!e))ight

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

match.Groups["Group1"].Captures
1 голос
/ 25 июня 2010

У вас есть другая проблема. Проверьте это:

string s = @"My weight is slight.";
Regex r = new Regex(@"(?<!e)ight\b");
foreach (Match m in r.Matches(s))
{
  s = s.Replace(m.Value, "ite");
}
Console.WriteLine(s);

выход:

My weite is slite.

String.Replace является глобальной операцией, поэтому, даже если weight не соответствует регулярному выражению, оно все равно изменяется при обнаружении slight. Вам необходимо выполнить сопоставление, поиск и замену одновременно; Regex.Replace(String, MatchEvaluator) позволит вам сделать это.

0 голосов
/ 24 июня 2010

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

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

(first)|(second)

можно получить доступс

match.Groups[1] // match group 2 -> second

Конечно, если у вас есть дополнительные скобки, которые вы не хотите включать, используйте оператор non-capture?:

((?:f|F)irst)|((?:s|S)econd)

match.Groups[1].Value // also match group 2 -> second
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...