Regex to match all new line characters outside of some tag
Question: I need to match all new line characters outside of a particular html tag or
pseudotag.

Here is an example. I want to match all `"\n"`s ouside of `[code] [/code]`
tags (in order to replace them with `<br>` tags) in this text fragment:

    
    
    These concepts are represented by simple Python classes.  
    Edit the polls/models.py file so it looks like this: 
    
    [code]  
    from django.db import models
    
    class Question(models.Model):
        question_text = models.CharField(max_length=200)
        pub_date = models.DateTimeField('date published') 
    [/code]
    

I know that I should use negative lookaheads, but I'm struggling to figure the
whole thing out.

Specifically, I need a PCRE expression, I will use it with PHP and perhaps
Python.


Answer: To me, this situation seems to be straight out of [Match (or replace) a
pattern except in situations s1, s2, s3
etc](http://stackoverflow.com/questions/23589174/match-or-replace-a-pattern-
except-in-situations-s1-s2-s3-etc/23589204#23589204). Please visit that link
for full discussion of the solution.

I will give you answers for both PHP and Python (since the example mentioned
django).

**PHP**

    
    
    (?s)\[code\].*?\[/code\](*SKIP)(*F)|\n
    

The left side of the alternation matches complete [code]...[/code] tags, then
deliberately fails, and skips the part of the string that was just matched.
The right side matches newlines, and we know they are the right newlines
because they were not matched by the expression on the left.

This PHP program shows how to use the regex (see the results at the bottom of
the [online demo](http://ideone.com/iXMIj8)):

    
    
    <?php
    $regex = '~(?s)\[code\].*?\[/code\](*SKIP)(*F)|\n~';
    
    $subject = "These concepts are represented by simple Python classes.
    Edit the polls/models.py file so it looks like this:
    
    [code]
    from django.db import models
    
    class Question(models.Model):
    question_text = models.CharField(max_length=200)
    pub_date = models.DateTimeField('date published')
    [/code]";
    
    $replaced = preg_replace($regex,"<br />",$subject);
    echo $replaced."<br />\n";
    ?>
    

**Python**

For Python, here's our simple regex:

    
    
    (?s)\[code\].*?\[/code\]|(\n)
    

The left side of the alternation matches complete `[code]...[/code]` tags. We
will ignore these matches. The right side matches and captures newlines to
Group 1, and we know they are the right newlines because they were not matched
by the expression on the left.

This Python program shows how to use the regex (see the results at the bottom
of the [online demo](http://ideone.com/Gg3VCV)):

    
    
    import re
    subject = """These concepts are represented by simple Python classes.  
    Edit the polls/models.py file so it looks like this: 
    
    [code]  
    from django.db import models
    
    class Question(models.Model):
        question_text = models.CharField(max_length=200)
        pub_date = models.DateTimeField('date published') 
    [/code]"""
    
    regex = re.compile(r'(?s)\[code\].*?\[/code\]|(\n)')
    def myreplacement(m):
        if m.group(1):
            return "<br />"
        else:
            return m.group(0)
    replaced = regex.sub(myreplacement, subject)
    print(replaced)
    

