How to join lines in between 2 conditions

Viewed 82

I'm listing a program to customly clean up a phonebook .vcf file.

I can't figure out how to place in a single string variable everything between start with /^NOTE.+:/ and end before /X-ACCOUNT.*:/. Please consider there were presence of \n I'd like preserve for future contact formatting:

ADR;WORK;X-SYNCMLREF507891:;;NUENSCfff STRASSE 3-5;RIESCHWEILER;;66509;Germania

ORG:aaaa & CO. KG

NOTE;ENCODING=QUOTED-PRINTABLE:Hall 30 F35=0A*ddddd@jggggine.com                   =0A014 =
 EURO                          =0A*kkkk@ggggne.com   =0A=
Bjjj@rrrLINE.COM 

X-ACCOUNT:Local Phone Account;Phone

maybe using any foreach loop. but I can't concatenate only what I need and stop at the right point:

foreach $in (<IN>){
if($in =~ /^NOTE.*:|=$/){
    unless($in =~ /^[A-Z]+:/){
        $in =~ s/(.+=$)\n//;
        $inn .= $1;
    }
}

$a = $a;

}

Any recomandations ?

2 Answers

More or less this:

$inn .= $in if (($in =~ /^NOTE/ .. $in =~ /^X-ACCOUNT/) && $in !~ /^X-ACCOUNT/);

Using implicit $_ would make it shorter, perhaps:

while(<IN>) {
   $inn .= $_ if (/^NOTE/ .. /^X-ACCOUNT/ and !/^X-ACCOUNT/);

See perlop for Range Operators and perhaps also perlop for why and is lower precedence than &&.

Less one-liney, perhaps more understandable : add a flag which indicates "currently accumulating lines in a variable"

$accumulating = 0;

foreach $in (<IN>){
  if ($in =~ /^NOTE/) {
    $accumulating = 1;
  }
  if ($in =~ /^X-ACCOUNT:/) {
    $accumulating = 0;
    # possibly : add some code which does something with $inn
  }

  if ($accumulating) {
    $inn .= $in;
  }
}
Related