2009-03-03 2 views
4

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

Каждая строка может быть или не быть частью большого блока цитируемого текста. Пример:

This line is not quoted. 
This part of the line is not quoted “but this is.” 
This one is not quoted either. 
“This entire line is quoted” 
Not quoted. 
“This line is quoted 
and so is this one 
and so is this one.” 
This is not quoted “but this is 
and so is this.” 

мне нужна замена RegEx, который не-обернуть жесткие обернутый процитированные строки, то есть, заменить «\ г \ п» с пространством, но только между фигурными кавычками.

Вот как это должно выглядеть после замены: (. Обратите внимание, как последние две строки были несколько строк во входном тексте)

This line is not quoted. 
This part of the line is not quoted “but this is.” 
This one is not quoted either. 
“This entire line is quoted” 
Not quoted. 
“This line is quoted and so is this one and so is this one.” 
This is not quoted “but this is and so is this.” 

Ограничения

  • В идеале нужно один вызов замены Regex
  • Использование библиотеки .NET RegEx
  • Котировки всегда начало/конец фигурные кавычки, а не простые двойные метки ("), что должно сделать это немного проще.

Важно Constraint

Это не прямой код .NET, я заселение таблицы "SearchFor/ReplaceWith" строки, которые затем вызываемые через RegEx.Replace. Я не имею возможность добавлять пользовательский код, как Match Оценщики, циклически захваченных групп и т.д.

Текущий ответ до сих пор, что-то вдоль линий:

r.Replace("(?<=“)\r\n(?=”)", " ") 

Очевидно, что я не даже близко еще.

Та же логика может быть применена, скажем, к цветному кодированию комментариев блока в коде программирования - что-либо внутри комментария блока не обрабатывается так же, как материал вне комментариев. (Код немного сложнее, поскольку разделители комментариев в конце и конце строки могут также законно существовать в литеральной строке, проблема, с которой мне здесь не приходится иметь дело.)

+0

Можете ли вы указать причину ограничений, особенно первых двух? – MarkusQ

+0

Добавлено ... это не настраиваемый код, это общий инструмент разбора/очистки, который я написал, который управляется таблицей из базы данных. Не существует простого способа написать одноразовый код для этой конкретной проблемы. – richardtallent

ответ

4

Предполагая, что все фигурные кавычки должным образом сбалансированы, это регулярное выражение должно делать то, что вы хотите:

@"[\r\n]+(?=[^“”]*”)" 

[\r\n]+ будет соответствовать один или несколько разделителей линий любого типа - Unix (\ п), DOS (\ r \ n) или старше Mac (\ r). Тогда взгляды утверждают, что впереди впереди ближайшая цитата и что между здесь и там нет открытой цитаты. Тогда ваш текст замены может быть простым символом пробела.

+0

Но что такое замена? – strager

+0

Заменой будет строка, состоящая из одного символа пробела. Все, что заменяется, является разделителем строк. –

+0

В этом случае я могу предположить, что фигурные кавычки правильно сбалансированы. Гений, Алан. Я знал, что должно быть что-то, что будет работать без рекурсии ... – richardtallent

0

Итак, нужно найти строку, начинающуюся с открывающей цитатой, за которой следует строка, которая содержит , а не, содержит заключительную цитату или любые символы \ r \ n, за которой следует серия из одного или нескольких символов \ r \ n, захватывает все, кроме терминала \ r \ n символов и заменить весь матч на захваченную часть.

- MarkusQ

+0

Итак, вы предлагаете что-то вроде: ("[^ \ r"] +) \ r \ n заменено на $ 1 [] Закрыть! который будет захватывать первый разрыв строки в цитируемом тексте, но не другие ... замена не является рекурсивной. – richardtallent

0

Я думаю, что самый простой способ будет соответствовать процитированные разделы с “(?s:.*?)” и использовать MatchEvaluator, чтобы удалить все переводы строк. Код MatchEvaluator может быть столь же просто, как

Replace(@"\s+", " "); 

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

+0

Я программирую набор вызовов RegEx, сделанных из таблицы в определенном порядке, а не для написания специального кода здесь. – richardtallent

+0

Хорошо, тогда посмотри мой другой ответ. –

0

Вы не можете делать то, что хотите, в пределах, которые вы описали.

Доказательство:

  • Ваша фиксированная таблица замен будет выполнять фиксированное число вызовов для замены (назовем это п)
  • Каждый заменить только будет в состоянии устранить фиксированное число обрывов линии (вызов это число m).

Поэтому

  • кавычках блок с т * брейков п + 1 строки не будут надлежащим образом рассмотрены.

Вам необходимо увеличить мощность вашей установки (например, путем более сложной замены, рекурсивных замен, неопределенного флага повторения или ...?) Или принять тот факт, что эта задача не может быть выполнена вашим двигателем.

- MarkusQ

+0

Если мне нужно было проверить сбалансированные кавычки, я думаю, что вы были бы правы, тем больше я смотрел на различные предложения. Алан придумал ответ, который работает на основе моего конкретного варианта использования, где я могу зависеть от сбалансированных котировок. Спасибо за помощь! – richardtallent

1

NB: Для тестирования регулярных выражений Я использую http://gskinner.com/RegExr/, который является очень полезным.

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

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

(?s) 

Затем вы хотите посмотреть-за выражение, чтобы соответствовать начала цитата:

(?<=“) 

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

(?=”) 

Теперь выражение, чтобы соответствовать какой-нибудь текст, а затем перевод строки, то текст:

([^”\r]*)\r?([^”\r]*) 

Обратите внимание, что есть две группы захвата для битов текста вокруг новой строки, поэтому вы можете включить этот текст в выражение replace. Это будет соответствовать тексту, который имеет только одну новую строку в кавычках. Для того, чтобы расширить это до двух символов новой строки, просто добавьте еще один дополнительный символ новой строки и необязательный следующий текст:

(?s)(?<=“)([^”\r]*)\r?([^”\r]*)\r?([^”\r]*)(?=”) 

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

Оставляя выражение что-то вроде этого:

r.Replace("(?s)(?<=“)([^”\r]*)\r?([^”\r]*)", "$1 $2") 

(Это не совсем правильно, как это будет добавить пробел после текста, даже если группа два не соответствует ...но это только начало)

+0

Элегантная форма грубой силы ... хорошая идея. К сожалению, может быть несколько сотен строк текста, которые необходимо объединить между фигурными цитатами. Ответ Алана ниже сделал трюк. – richardtallent

+0

На самом деле, поскольку вы отметили его как принятый, этот ответ теперь выше, а не ниже. :-) –

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