Регулярные выражения и группы без записи в C # - PullRequest
0 голосов
/ 19 августа 2011

У меня проблема с регулярным выражением в C #. Я использовал шаблоны тезисов в F #, и он отлично работает, поэтому я не понимаю, почему он не будет работать в C #.

Итак, допустим, у меня есть входной файл мулинов. Мне нужно проанализировать этот файл для конкретных данных:

Exemple:

    Lorem ipsum dolor sit amet, consectetur adipiscing elit (Token1 : 42)
    Aliquam id ante ut ante tempus fringilla Token2 (ante ut ) : 45
    Morbi varius adipiscing lacus, eget pellentesque tellus vulputate Token3 :  43

Мне нужно извлечь числа, записанные после Token1, Token2, Token3, в одном совпадении (т.е. просто хочу получить мой номер в результате). Шаблоны, которые я использовал в F #, следующие:

PatternToken1 = "(?:Token1 : )(\d+)"
PatternToken2 = "(?:Token2.* : )(\d+)"
PatternToken3 = "(?:Token3 : )(\d+)"

Итак, моя проблема заключается в следующем: шаблон, соответствующий моей входной строке в F #, даст мне следующие результаты:

 MatchedToken1 = 42
 MatchedToken2 = 45
 MatchedToken3 = 43

В C # я бы получил следующие результаты:

 MatchedToken1 = Token1 : 42
 MatchedToken2 = Token2 (ante ut ) : 45
 MatchedToken3 = Token3 :  43

Почему это работает в F #, а не в C #? Какой тип шаблона я должен использовать, чтобы он работал в C #?

EDIT: Вот код, который я использую, чтобы соответствовать моим шаблонам в c #:

 abstract class  PatternMatcherBaseEntity<T>
{
    protected Regex Pattern;
    protected T Match;


    private static TK Convert<TK>(string input)
    {
        TK res=default(TK);
        var converter = TypeDescriptor.GetConverter(typeof(TK));
        if(converter != null)
        {
            try
            {
                res = (TK) converter.ConvertFromString(input);
            }
            catch (Exception)
            {
                res = default(TK);
            }

        }
        return res;
    }


    protected bool Matcher(string s)
    {
        var res = false;
        //var matchedData = Regex.Match(s, Patterm);
        var content = Pattern.Matches(s);
        if(content.Count>0)
        {
            //Match = Convert<T>(content.Value);
            Match = Convert<T>(content[0].Value);
            res = true;
        }
        return res;
    }

    public T MatchGetter(String stringToMatch)
    {
        T ret = default(T);
        if(stringToMatch != String.Empty)
        {
            ret = stringToMatch.Match()
            .With(Matcher, x => Match)
            .Else(x => default(T))
            .Do();
        }
        return ret;
    }
}

кстати, я проверял использование дословных и escape-строк. В противном случае он не будет компилироваться

Ответы [ 4 ]

1 голос
/ 19 августа 2011

Попробуйте использовать следующее:

PatternToken1 = "(?<=Token1 : )(\d+)"
PatternToken2 = "(?<=Token2.* : )(\d+)"
PatternToken3 = "(?<=Token3 : )(\d+)"
1 голос
/ 19 августа 2011
(?:Token1 : )(\d+)
             ^   ^

С помощью этих скобок вы создаете группу захвата, которая помещает соответствие из скобок в группу захвата.

Вы используете это сейчас, как это

var content = Pattern.Matches(s);

сейчас Matches возвращает массив, где

content[0] содержит полную совпадающую строку

content[1] содержит совпадающую часть группы 1

и здесь

Match = Convert<T>(content[0].Value);

вы используете не ту часть MatchCollection Array content

Ваш результат в группе 1, поэтому вам нужно получить группу 1

Match = Convert<T>(content[1].Value);
0 голосов
/ 19 августа 2011

В C # вы хотите, чтобы (? :) совпадал, но не включался в результат матча:

Regex.Match(str, @"(?:Token1) : (\d+)"); // result =  42
Regex.Match(str, @"(?:Token2).* : )(\d+)"); // result = 45
Regex.Match(str, @"(?:Token3).+:.+\d+"); // result = 43

РЕДАКТИРОВАТЬ - случайно там была случайная пара - спасибо комментатору за указание - также, полностью неправильно понял суть вопроса ... думал, что ОП хотел получить совпадение со словом - забавная часть, я даже открываю вопрос с "сопоставлять, но не включать".Не уверен, о чем я думал - в любом случае, новый код и на этот раз копирование / вставка, чтобы избежать лишних слов ...

    string str = "Lorem ipsum dolor sit amet, consectetur adipiscing elit (Token1 : 42)      Aliquam id ante ut ante tempus fringilla Token2 (ante ut ) : 45      Morbi varius adipiscing lacus, eget pellentesque tellus vulputate Token3 :  43  ";
    Match m1 = Regex.Match(str, @"(?<=Token1 : +)\d+");
    Match m2 = Regex.Match(str, @"(?<=Token2.* : +)\d+");
    Match m3 = Regex.Match(str, @"(?<=Token3 : +)\d+");
    MatchCollection mAll = Regex.Matches(str, @"(?<=Token\d[^\:]+: +)\d+");
0 голосов
/ 19 августа 2011

Я не знаю F #, но в C # вам нужно избегать обратной косой черты, удваивая их \\, или использовать префикс @ string:

PatternToken1 = "(?:Token1 : )(\\d+)";
PatternToken2 = @"(?:Token2.* : )(\d+)";
PatternToken3 = @"(?:Token3 : )(\d+)";
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...