Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Общие вопросы по .NET и C# > Регулярное выражение


Автор: Pankon 21.2.2008, 14:36
Есть строки примерно такого вида или подобные(с вложенными и не вложенными тегами <iif>):
Код

test000<iif>test001</iif>test002<iif>test003<iif><iif>test004</iif>test005</iif></iif>test006

Мне нужно получить набор строк:
Код

test000
<iif>test001</iif>
test002
<iif>test003<iif><iif>test004</iif>test005</iif></iif>
test006

Проблема - написать правильное регулярное выражение (неправильные я и сам уже перепробовал  smile )


Автор: source777 24.2.2008, 01:05
Цитата(Pankon @  21.2.2008,  14:36 Найти цитируемый пост)
Проблема - написать правильное регулярное выражение
Да, задача действительно непростая, думаю одним регэкспом тут не обойтись...
Пока можешь попробовать хоть и не оптимальный, но вполне рабочий воркэраунд:
Код

            string text = @"test000<iif>test001</iif>test002<iif>test003<iif><iif>test004</iif>test005</iif></iif>test006";
            string expr0 = @"(.*?)(<iif>";
            string expr1 = "";
            string expr2 = ")";
            int open_tags, close_tags;
            Match match;
            MatchCollection match_open, match_close;
            List<string> res = new List<string>();
            do
            {
                do
                {
                    expr1 = ".*?</iif>" + expr1;
                    match = Regex.Match(text, expr0 + expr1 + expr2);
                    match_open = Regex.Matches(match.Groups[2].ToString(), "<iif>");
                    match_close = Regex.Matches(match.Groups[2].ToString(), "</iif>");
                    open_tags = match_open.Count;
                    close_tags = match_close.Count;
                } while (open_tags - close_tags > 0);
                res.Add(match.Groups[1].ToString());
                res.Add(match.Groups[2].ToString());
                text = text.Remove(1, match.Groups[0].ToString().Length);
                if (!text.Contains("<iif>"))
                {
                    res.Add(text);
                    break;
                }
            } while (text.Length > 0);

            foreach (string v in res)
                Console.WriteLine(v);



Автор: marcusmae 24.2.2008, 03:12
Pankon, я долго смотрел на Ваш пример, и, если правильно понял, то задача состоит в том, чтобы из размеченной строки последовательно извлечь нулевые (без тегов) и первые (заключённого в одну пару <lif>ов) по вложенности тексты. Правильно? Если так, то здесь имеет место быть задача о вложенных скобках. В отличие от классических автоматов, на регекспах эта задача решается, поскольку последние дополнительно вооружены групп-рекурсиями :

Код

            string target =
                "test000(test001)test002(test003((test004)test005))test006";

            Regex block = new Regex(
                @"\((?>[^()]+|\((?<GROUP>)|\)(?<-GROUP>))*(?(GROUP)(!?))\)");            

            MatchCollection matches = block.Matches(target);

            foreach (Match match in matches)
                Console.WriteLine(match.Groups[0]);

            Console.WriteLine("Done.");
            Console.ReadKey();


Результат :

Цитата

(test001)
(test003((test004)test005))
Done.


Часть требуемого результата получена. Но выглядит сурово, правда? smile Если нет такой необходимости возиться с регекспами, то проще воспользоваться парсером (регекспы - это больше лексеры). То есть, например, инициализировать нулём целочисленную переменную - индикатор и пройти по строке. Как только встречается "(" - делать к ней +1, ")" - делать -1. Строка будет распадаться на токены в тех местах, где индикатор будет из нуля переходить в не ноль и наоборот.

Автор: Pankon 3.3.2008, 17:03
source777, marcusmae,  спасибо за советы, обязательно проверю ваши примеры.


Цитата(marcusmae @  24.2.2008,  03:12 Найти цитируемый пост)
возиться с регекспами, то проще воспользоваться парсером
  smile, честно говоря, не хотел "возится с парсером".... smile 

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)