I have this lines:
alpha: beta
beta: alpha, beta
omega: beta, gamma, alpha
gamma:
alpha
beta
gamma
epsilon: alpha
I want to join line contains
This should do the same as RCs code, but a little bit shorter:
my @lines;
while(<FILE>) {
chomp;
if(m/^\w+:\s(\w+(,\s)?)*$/) {
push @lines, $_;
} else {
$lines[$#lines] .= ", " unless($lines[$#lines] =~ m/^\w+:\s?$/);
$lines[$#lines] .= $_;
}
}
print join "\n", @lines;
Here's a quick and dirty version:
#!/usr/bin/perl
use strict;
use warnings;
my $prevLine = "";
my @others;
for(<DATA>) {
chomp;
if (/:\s*$/) { # lines ends with : and potential space after
$prevLine = $_;
} elsif (!/:/) { # line doesn't contain ':'
push(@others, $_);
} elsif ($prevLine eq "") { # this is a "x: y, z" line, nothing in buffer
print $_ . "\n";
} else { # this is a "x: y, z" line, with a previous line in buffer
print $prevLine . join(", ", @others) . "\n" . $_ . "\n";
}
}
__DATA__
alpha: beta
beta: alpha, beta
omega: beta, gamma, alpha
gamma:
alpha
beta
gamma
epsilon: alpha
Output:
alpha: beta
beta: alpha, beta
omega: beta, gamma, alpha
gamma: alpha, beta, gamma
epsilon: alpha
This also works if the input is provided in a file as an argument to the script, and is a little shorter:
$/=$.;$_=<>;s/\s?\n/, /g;s/, (\w+:),?/\n$1/g;s/, $/\n/;print
It's not very readable, but it works with strict
and warnings
.
Output:
alpha: beta
beta: alpha, beta
omega: beta, gamma, alpha
gamma: alpha, beta, gamma
epsilon: alpha
It can probably be shortened even further. -ape
or #!perl -ap
would be a good start.