А запустить и проверить разве сложно?
Во-первых второй аргумент функции у вас это анонимная функция и никакой $content в ней не будет доступно, а чтобы было доступно, нужно передать эту переменную в нее - function( $match_before ) use($content) { ...
Во-вторых не изменение строки внутри функции, а для этого переменная должна передаваться в функцию по ссылке - function( $match_before ) use(&$content) { ..., а возвращать измененные фрагменты, иначе последствия непредсказуемы.
Запускайте свой код и вы как минимум получите ошибку. Вы что пишите, а проверять не проверяете?
В том, что вы нагородили в preg_replace_callback нет никакого смысла, да и вообще во всем коде.
Что есть причина пустой строки, это двойное \r\n или \n. При этом непосредственно \r\n можно трактовать также пустой строкой. Что вы хотите получить вне тегов - заменить двойной перевод строки одиночным или сохранить оригинал?
$s = 'aaa
bbb
<div>ccc
ddd</div>
eee
<pre>fff
ggg</pre>';
$s = preg_replace_callback('/<div>.+<\/div>|<pre>.+<\/pre>/s', function($v) {
return str_replace('<br />', '', $v[0]);
}, nl2br($s));
echo $s;
//затем вместо nl2br($s) пропишите так:
preg_replace('/^\s+$/m', '<br />', $s)
//и посмотрите на разницу
Примечание - preg_replace_callback для посмотреть, все это можно сделать и без нее.