At each position you need to check whether or not you are inside a valid <pre>
tag:
~(?s)(?<!<pre>)\R(?!</pre>)(?=((?!<pre>).)*</pre>)~
Explanation:
(?s)
(?<!<pre>)
\R
(?!</pre>)
(?=
((?!<pre>).)*
</pre>
)
Live demo
Note: It doesn't provide expected results if you have nested <pre>
tags (!)
But if you are comfortable to work with DOM
then there is a more suitable solution for this:
<?php
$html = <<< HTML
<div>
<div>
test
test
test
</div>
<pre>
Line one
Line two
Line three
Line four
Line five
Line six
</pre>
</div>
HTML;
$dom = new DOMDocument;
@$dom->loadHTML($html, LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD);
$preTags = $dom->getElementsByTagName('pre');
foreach ($preTags as $key => $pre) {
$pre->nodeValue = str_replace(PHP_EOL, '~*~*', $pre->nodeValue);
}
echo str_replace("~*~*", '<br />', $dom->saveHTML());
Output:
<div>
<div>
test
test
test
</div>
<pre><br />Line one<br />Line two<br />Line three<br />Line four<br />Line five<br />Line six<br /></pre>
</div>