Нужна помощь с регулярным выражением, не заменяющим все экземпляры выражения - PullRequest
2 голосов
/ 08 августа 2009

В течение всего этого дня я бился головой об стену и приближаюсь к этому. В поисках свежей перспективы.

Образец входного текста:
(разрывы строк добавлены для ясности, а не в реальных данных)

</div>#My Novel<br />  
##Chapter1<br />  
It was a dark and stormy night<br />
##Chapter 2<br />
The End

Желаемый выход

</div><h1>My Novel</h1><br />
<h1>Chapter1</h1><br />  
It was a dark and stormy night<br />  
<h1>Chapter 2</h1><br />  
The End

Фактический объем производства

</div><h1>My Novel</h1><br />
##Chapter1<br />  
It was a dark and stormy night<br />  
<h1>Chapter 2</h1><br />  
The End

Вот выражение совпадения
(отформатировано для удобства чтения, комментарии / переносы строк не выражены)

(?<preamble>
    (                             
        ([<]\/\w+\d*[>])|([<]\w+\d*\s*\/[>])   #</tag> or <tag />
    )
    \s*  #optional whitespace                       
)

(?<hashmarks>
    \#{1,6}      #1-6 hash marks
)    

(?<content>
    .+?          #header content
 )      

(?<closing>
    ([<](br|\/\s*br|br\s*\/)[>])   #<br>,</br>, or <br />
)

Вот выражение для замены

${preamble}<h1>${content}</h1>${closing}

Если это имеет значение, я использую следующую C # regex.replace overload:

Regex.Replace(Source,SrchExp,ReplExpr,RegexOptions.IgnoreCase)

Вопрос (наконец)
Кто-нибудь может понять, почему он заменяет #My Novel и ## Chapter 2, но не ## Chapter 1?

Извините за длинный пост, и, надеюсь, я ничего не пытался отформатировать, чтобы сделать его читаемым для SO.

Обновление:

Еще одна вещь, которая может помочь. Добавление дополнительного тега разрыва сразу после «Романа» заставляет приведенный код начать работать отлично. Понятия не имею почему.

Образец входного текста (изменен):

</div>#My Novel<br /><br />
##Chapter1<br />  
It was a dark and stormy night<br />
##Chapter 2<br />
The End

1 Ответ

2 голосов
/ 08 августа 2009

Вот тот, который был на самом деле проверен и, кажется, работает.

Проблема в том, что как только совпадение найдено, поиск продолжается именно там, где остановился первый. В результате закрытие <br /> из #My Novel больше не будет зафиксировано, и поэтому #Chapter1 пропущено.

Для захвата #Chapter1 -подобных конструкций в любом случае мы можем использовать утверждение взгляда . Lookbehinds усиливают присутствие префикса, даже если он продолжается до текущей позиции. Это также избавляет от необходимости помещать его в строку замены:

  • Заменить (?<preamble> на (?<=

  • Затем в строке замены удалите часть ${preamble}.

Общее поисковое выражение теперь выглядит так:

(?<=             # removed the preamble capture and replaced with a lookbehind
    (                             
        ([<]\/\w+\d*[>])|([<]\w+\d*\s*\/[>])   #</tag> or <tag />
    )
    \s*  #optional whitespace                               
)

(?<hashmarks>
    \#{1,6}      #1-6 hash marks
)    

(?<content>
    .+?          #header content
 )      

(?<closing>
    ([<](br|\/\s*br|br\s*\/)[>])   #<br>,</br>, or <br />
)

И строка замены выглядит так:

<h1>${content}</h1>${closing}

Наш вывод теперь верно:

</div><h1>My Novel</h1><br />
<h1>Chapter1</h1><br />
It was a dark and stormy night<br />
<h1>Chapter 2</h1><br />
The End
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...