Advanced multi-conditonal split with an regex in Perl I would like to split a string on multiple conditions such as:


After each /;/
After each /{/ or /}/
After each /\w+:/ but not after /\w+:\s+\{/
After each /#\w.*$/


I've found that I can keep a pattern and split before it with

/(?=pattern)/


or split after it (if the pattern has a fixed width)

/(?&lt;=pattern)/


or split after it (if the pattern has a variable width)

/pattern\K/


or even remove the pattern during the operation

/pattern/


With all this knowledge I wrote this:

#!/usr/bin/perl    
$_ = do { local $/; &lt;DATA&gt; };
s/\#\w.+\n\K|\n//g;

my @content = split /(?:(?&lt;=[;{}])|(?&lt;=:)(?!\s*\{)|#\w.*\$\K)/, $_;

print join "\n", @content;

__DATA__
carrot;
#orange
apple: {pear; { cabbage; } }
#passion
sprout: celeri;
tomato;


Where the output should be this (after manually reindenting it):




carrot;
#orange
apple: {
  pear;
  {
    cabbage;
  }
}
#passion
sprout:
celeri;
tomato;



I am not really happy with this method for multiple reasons: 


I cannot use a x regex in split like split m/re/x to make the regex more readable
I need to treat the exception for the special case /^\s*#.*$/ where I cannot remove CR otherwise I will get for instance #passionsprout:


Can I do a better job?
Think the other way around: try to add a newline to all characters that need one. That way your regex is a bit simpler.

#!/usr/bin/perl -w

use strict;

my $content = do { local $/; &lt;DATA&gt; };

my $regex = qr{
  (?m)
    (^
     |
     :\s*
    )
    \{                  # open curly brace preceded by 
                        # beginning of line
                        # OR
                        # colon

  |                     # OR
    [:;\}]              # any of these characters
    (?!\s*\n)           # NOT followed by newline
}x;

$content =~ s/($regex)/$1\n/g;
print $content, "\n";