Разбор многострочного BBCode с помощью C # Regex

Я работаю над классом C # для синтаксического анализа BBCodes из текста, извлеченного из базы данных, для сообщений PHPBB. В PHPBB добавлен собственный BBCode, который выглядит следующим образом:

[deck={TEXT1}]{TEXT2}[/deck]

Что в базе данных выглядит так:

[deck=FirstText:13giljne]Large Multiline Text[/deck:13giljne]

Я пытаюсь заменить это с помощью Regex в C #. Мой C # выглядит так:

string text = "[deck=FirstText:13giljne]Large Multiline Text[/deck:13giljne]";
string replace = "my replacement string";
string pattern = @"\[deck=((.|\n)*?)(?:\s*)\]((.|\n)*?)\[/deck(?:\s*)\]";
RegexOptions options = RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.Singleline;
Regex regex = new Regex(pattern, options);
string result = regex.Replace(text, replace);

Я почти уверен, что все сводится к тому, что мой шаблон Regex ошибочен. Что меня не удивляет, поскольку Regex - не совсем моя сильная сторона.

Заранее спасибо. Любая помощь приветствуется.

РЕДАКТИРОВАТЬ: поскольку некоторые люди сочли это непонятным, я добавлю более крупные примеры.

Исходный текст:

[deck=Foo:13giljne]
    Item #1
    Item #2
    Item #3
    Item #4
[/deck:13giljne]

Желаемый результат:

<span>Foo</span>
<div>
    Item #1
    Item #2
    Item #3
    Item #4
</div>

Надеюсь, это дает более четкое представление о том, что я пытаюсь сделать.


person BRW    schedule 15.11.2011    source источник
comment
Если вы можете уточнить немного больше ... Я пытаюсь заменить это, используя Regex в C #, пытаясь заменить что чем?   -  person m0skit0    schedule 15.11.2011
comment
@ m0skit0 Я пытаюсь заставить регулярное выражение соответствовать строке в переменной с именем text и заменить ее строкой в ​​переменной с именем replace.   -  person BRW    schedule 15.11.2011
comment
Но разве это не вся строка? Почему бы просто не использовать replace вместо text? Я не понимаю твоей проблемы ...   -  person m0skit0    schedule 15.11.2011
comment
@ m0skit0 Я просто поместил эту небольшую часть в text как пример строки, которую я пытаюсь сопоставить. Фактическое значение text содержит другой текст до и после части, которую я пытаюсь сопоставить. Это значение извлекается прямо из базы данных, и я пытаюсь проанализировать BBCodes и заменить их, прежде чем они будут отображены.   -  person BRW    schedule 15.11.2011
comment
Я предполагаю, что вы пытаетесь избавиться от тегов [deck=...] и [/deck...] и хотите только текст между тегами BBCode. Это верно?   -  person jwheron    schedule 15.11.2011
comment
Можете ли вы показать пример текста перед заменой, а затем текст после замены, чтобы я мог увидеть, как должен выглядеть конечный результат, которого вы пытаетесь достичь?   -  person M3NTA7    schedule 15.11.2011
comment
@jwiscarson Вы близки. Я пытаюсь заменить [deck=...] и [/deck...] на HTML. Думаю, я отредактирую вопрос, приведя несколько примеров.   -  person BRW    schedule 15.11.2011


Ответы (4)


Я думаю, что ваше регулярное выражение показывает, что вам нужно сопоставить «Первый текст» и «Большой многострочный текст».

\[deck=([^\:]+?):(?:[^\]]+)\]([^\[]+?)\[/deck:(?:[^\]]+)\]

Это должно помочь, и это очень похоже на ваше.

person dereli    schedule 15.11.2011
comment
Я думаю, у вас ошибка. Замените ([^\]]+?) на ([^\[]+?) в части, которая пытается соответствовать Large Multiline Text. Вы ищете все до следующей открытой скобки, а не до следующей закрытой скобки. - person Jim Mischel; 15.11.2011
comment
Спасибо, Джим. Копировать-вставить припев. - person dereli; 16.11.2011

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

string text = "[deck=FirstText:13giljne]Large Multiline Text[/deck:13giljne]";

Напишите выражение, соответствующее первой части:

string firstPart = "\[deck=[^\]]+\]";

[^\]]+ говорит: «Сопоставьте все, что не является символом ]».

Убедитесь, что он соответствует:

Match m = Regex.Match(text, firstPart);

Затем закрепите вторую часть:

string firstAndSecond = firstPart + "[^\[]*";

И проверьте это.

Как только это сработает, вы можете добавить последнюю часть:

string search = firstAndSecond + "\[/deck[^\]]\]";

Последнее регулярное выражение будет (\[deck=[^\]]+\])([^\[]+)(\[/deck[^\]]+\].

Я сгруппировал отдельные части, чтобы их было легче увидеть. Вы можете удалить группы, если хотите, или сделать их не захватывающими.

РЕДАКТИРОВАТЬ:

Из вашего редактирования я вижу, что вы хотите захватить FirstText и три группы:

string search = "(\[deck=([^:]+):[^\]]+\])([^\[]+)(\[/deck[^\]]+\]";

Строка замены будет выглядеть примерно так:

string replace = "<span>$2</span>\n<div>$3</div>";
person Jim Mischel    schedule 15.11.2011
comment
Мне нужно отдельно сопоставить первую часть с [deck=FirstText:13giljne], потому что мне нужно использовать то, что находится между [deck= и :13giljne]. - person BRW; 15.11.2011
comment
Ваше последнее регулярное выражение все еще не соответствует строке. Тем не менее, спасибо за помощь. - person BRW; 15.11.2011

Проверьте STML Parser на GitHub или Nuget. Он не использует RegEx, но намного эффективнее и быстрее.

введите описание изображения здесь

person Tawani    schedule 06.01.2015

Если вы хотите заменить "[deck=FirstText:13giljne]Large Multiline Text[/deck:13giljne]", не используйте регулярное выражение. Используйте Заменить.

string result= text.Replace("[deck=FirstText:13giljne]Large Multiline Text[/deck:13giljne]", replace);

Регулярные выражения обычно используются там, где строка не полностью известна, но известна ее структура.

person m0skit0    schedule 15.11.2011
comment
Это не поможет. FirstText не является статическим значением,: 13giljne не является статическим значением, а Large Multiline Text не является статическим значением. Это все переменные, значения которых я не могу контролировать. Это был всего лишь пример того, что МОЖЕТ выйти из базы данных, и мне нужно сопоставить. - person BRW; 15.11.2011
comment
@ m0skit0, ммм, я не думаю, что вы вполне уловили дух того, о чем просит OP. - person Kirk Woll; 15.11.2011
comment
Я думаю, Уэйн неплохо поработал, особенно по первому вопросу. - person jwheron; 15.11.2011
comment
Тогда почему ты ему не отвечаешь? : P Мне все равно, если это его первый вопрос. Ему / ей следует лучше объяснить, чего он / она хочет. Период. В любом случае, удачи, Уэйн. - person m0skit0; 15.11.2011
comment
Я постараюсь сказать это без обвинений. Я не знаю, проводили ли вы время в интерфейсе обзора или читали много вопросов от новых людей. Не у всех есть многолетний опыт программирования. Не все понимают, сколько подробностей нужно для того, чтобы правильно отвечать на вопросы. Вам следует позаботиться о том, чтобы это первый вопрос Уэйна, потому что мы все когда-то были в этом месте, и кто-то должен был помочь нам, когда мы не имели ни малейшего представления о том, что происходит. - person jwheron; 15.11.2011
comment
Если вы посмотрите комментарии к вопросу, вы увидите, что я пытался понять, что он имел в виду. И я не чувствую себя обвиняемым, потому что я ответил на гораздо больше вопросов, чем задал на самом деле, и, конечно, я не чувствую вины, помогая людям. Это правда, что некоторые люди на самом деле забывают, что они нуждаются в помощи, а не я. Кстати, спасибо за комментарий. - person m0skit0; 15.11.2011