Вот как первая альтернатива взгляда Стива Левитана может быть применена к вашей проблеме:
var output = s.replace(/(<pre>[\s\S]*?<\/pre>)|\n/g, function($0, $1){
return $1 ? $1 : '<p/>';
});
Когда он достигает элемента <pre>
, он захватывает все это и подключает его обратно к выходу. Он никогда не видит новые строки внутри элемента, просто поглощает их вместе со всем остальным содержимым. Таким образом, когда \n
в регулярном выражении соответствует совпадению с новой строкой, вы знаете, что оно не находится внутри элемента <pre>
и должно быть заменено на <p/>
.
Но не делайте ошибку, рассматривая эту технику как хак или обходной путь; Я бы порекомендовал этот подход, даже если бы смотрели . При подходе обходного подхода регулярное выражение должно проверять каждую новую строку и применять обходные пути каждый раз, чтобы увидеть, следует ли ее заменить. Это много ненужной работы, плюс регулярное выражение гораздо более сложное и менее обслуживаемое.
Как всегда при использовании регулярных выражений в HTML, я игнорирую множество факторов, которые могут повлиять на результат, таких как комментарии SGML, секции CDATA, угловые скобки в значениях атрибутов и т. Д. Вам нужно будет определить, какой из этих факторов вам приходится иметь дело в вашем случае, и какие из них вы можете игнорировать. Когда дело доходит до обработки HTML с помощью регулярных выражений, не существует такого понятия, как общее решение.