3
\$\begingroup\$

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)

/(?<=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 $/; <DATA> };
s/\#\w.+\n\K|\n//g;

my @content = split /(?:(?<=[;{}])|(?<=:)(?!\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?

\$\endgroup\$
3
\$\begingroup\$

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{
  (?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";
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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