Модераторы: Partizan, gambit
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Регулярное выражение, Текст с вложенными и не вложенными тегам 
:(
    Опции темы
Pankon
  Дата 21.2.2008, 14:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 739
Регистрация: 2.6.2005

Репутация: 3
Всего: 5



Есть строки примерно такого вида или подобные(с вложенными и не вложенными тегами <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 )


PM MAIL   Вверх
source777
Дата 24.2.2008, 01:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1878
Регистрация: 12.3.2007

Репутация: 4
Всего: 56



Цитата(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);





--------------------
Если бы программистам платили за то, чтобы убирать код из программы вместо того, чтобы добавлять его, программы были бы намного лучше © Николас Негропонте
PM MAIL   Вверх
marcusmae
Дата 24.2.2008, 03:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


stravaganza
**


Профиль
Группа: Участник
Сообщений: 874
Регистрация: 26.3.2006

Репутация: 22
Всего: 39



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. Строка будет распадаться на токены в тех местах, где индикатор будет из нуля переходить в не ноль и наоборот.

Это сообщение отредактировал(а) marcusmae - 24.2.2008, 03:15


--------------------
ἀπὸ μηχανῆς θεός
PM MAIL ICQ GTalk   Вверх
Pankon
Дата 3.3.2008, 17:03 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 739
Регистрация: 2.6.2005

Репутация: 3
Всего: 5



source777, marcusmae,  спасибо за советы, обязательно проверю ваши примеры.


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

PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Прежде чем создать тему, посмотрите сюда:
mr.DUDA
THandle

Используйте теги [code=csharp][/code] для подсветки кода. Используйтe чекбокс "транслит" если у Вас нет русских шрифтов.
Что делать если Вам помогли, но отблагодарить помощника плюсом в репутацию Вы не можете(не хватает сообщений)? Пишите сюда, или отправляйте репорт. Поставим :)
Так же не забывайте отмечать свой вопрос решенным, если он таковым является :)


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, mr.DUDA, THandle.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Общие вопросы по .NET и C# | Следующая тема »


 




[ Время генерации скрипта: 0.0452 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.