2011-01-21 3 views
2

Начнем с небольшого примера; У меня есть следующий текст:C# regexp для вложенных тегов

[[некоторый тег [[с тегом вложенного]] и снова]]

Я хотел бы, чтобы соответствовать [[с тегом вложенной]] но не [[какой-либо бирка [[с биркой гнездо]]. Простой

\[\[(?<content>.+?)\]\] 

очевидно не работал. Так что я создал регулярное выражение:

\[\[(?!.*?\[\[.*?\]\].*?)(?<content>.+?)\]\] 

К сожалению, он ничего не совпадает с использованием C# (с MatchOptions.SingleLine), в то время как preg_match PHP работает отлично.

Любые подсказки/идеи? Любая помощь приветствуется.

+0

У меня нет проблем с запуском регулярного выражения в C# с помощью опции SingleLine. Он возвращает [[с тегом вложенные]] правильно. Можете ли вы разместить свой код? –

+0

Я не уверен, что вижу проблему. Я создал 'System.Text.RegularExpressions.Regex', используя ваш второй шаблон и' RegexOptions.Singleline', а затем вызывается 'Match' в вашей строке примера. Он вернулся с одним захватом «[[с вложенным тегом]]». –

+0

@Harry: Попробуйте с этим вводом: '[[outer1 [[inested1]] outer2 [[inested2]] outer3]]'. Если я правильно понял вопрос, он должен соответствовать «nested1» и «nested2», но он соответствует только «nested2». –

ответ

3

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

var match = Regex.Match(input, @"^.*(\[\[(.*?)\]\])", RegexOptions.Singleline); 

Это работает, потому что находит последний[[ (так что не более [[ после него , поэтому он не может содержать вложенные теги), а затем сразу после ]]. Конечно, это предполагает корректность; если у вас есть строка, где скобки начала и конца не совпадают правильно, это может завершиться неудачно.

После того, как вы нашли сокровенный кронштейн, вы можете удалить его из входной строки:

input = input.Remove(match.Groups[1].Index, match.Groups[1].Length); 

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

+0

Я боюсь, что это не дает то, что я (и вы, вероятно) захотел: он соответствует первому [[. В любом случае, спасибо за ответ. – FoxException

+0

@Avaer: Нет, это не так. Он работает отлично. Ты это пробовал? Если вы считаете, что это не удается, укажите пример ввода, для которого он не работает. – Timwi

+0

Я должен вам извиниться, я не наблюдал содержание групп [1], но в моем потоке только что проверил Value. Он работает. Еще раз спасибо. – FoxException

3

Действительно ли это будет подходящий матч?

[[ with [ single ] brackets ]] 

Если нет, то это регулярное выражение должно делать:

\[\[(?<content>[^][]*)\]\] 

[^][] соответствует любому символу, который не [ или ]. Если одиночные скобки являются разрешены, попробуйте следующее:

\[\[(?<content>(?:(?!\[\[|\]\]).)*)\]\] 

(?!\[\[|\]\]). соответствует любому символу, но только убедившись, что это не начало последовательности [[ или ]].

+0

Это прекрасно работает. Спасибо! – FoxException

+0

@Avaer: Так делает моя, а моя проще. – Timwi

+0

@ Тимви, я предпочитаю предложение Алана. Возможно, ваше проще в том смысле, что регулярное выражение короче, но выясняет, почему он работает (потому что первый '. *' Потребляет всю строку, а затем обратные треки до последнего '[[') не являются интуитивными. Кроме того, ваше предложение не обрабатывает такие случаи, как 'aaa [[bbb ccc]] [[ddd'. –

Смежные вопросы