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


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


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


or even remove the pattern during the operation


With all this knowledge I wrote this:

$_ = do { local $/; <DATA> };

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

print join "\n", @content;

apple: {pear; { cabbage; } }
sprout: celeri;

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

apple: {

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?


1 Answer 1


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 $/; <DATA> };

my $regex = qr{
    \{                  # open curly brace preceded by 
                        # beginning of line
                        # OR
                        # colon

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

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

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.