Perl -- Script to re-format data

Hi,

I have a file with data in the following format

BOX
-1.000000 -1.000000 0.000000
30.00000 14.00000 0.1000000
0.000000 0.000000 0.000000
0.000000
0.000000
CYLINDER
3.595000 2.995000 0.000000
0.5100000 2.000000
Z
0.000000 0.000000
0.000000

I want to convert these files into the following format instead

_Box -1.000000,-1.000000,0.000000 30.00000 14.00000 0.1000000
_Cylinder 3.595000,2.995000,0.000000 0.5100000 2.000000

Essentially these are the things I have done to re-format it.

  1. Added "_" before BOX and CYLINDER and then changed these strings to lowercase (apart from the first letter).
  2. The first line after BOX and CYLINDER moved to the same line as _Box and _Cylinder, but commas are added to separate the three numbers on that line.
  3. The second line after BOX and CYLINDER moved to the same line as before - but separated using spaces.
  4. Delete 3rd, 4th and 5th lines after BOX and CYLINDER.

I'd like to do this in perl if possible. So far I have the following script,

$infile="box_cyl.txt";
open(IN,$infile);
@lines=<IN>;

for ($i=1;$i<=$#lines;$i++){
	if($lines[$i] =~ 'CYLINDER'){
		@line1 = split (/ /,$lines[$i+2]);
                @line2 = split (/ /,$lines[$i+3]);
	} 
        elsif($lines[$i] =~ 'BOX'){
		@line1 = split (/ /,$lines[$i+2]);
                @line2 = split (/ /,$lines[$i+3]);
	}
}

Which basically finds the location of BOX and CYLINDER and reads the data in the first and second lines after BOX and CYLINDER is found. I'm new to perl and I'm not sure how to achieve the rest.

Many thanks!

Perhaps a heavily commented and hard coded example?

#!/usr/bin/perl

use strict;
use warnings;

my $in="file";

open my $fh, '<', $in or die "Could not read $in: $!\n";

# start reading the file
while ( my $line = <$fh> ) {

    # find line with pattern BOX or CYLINDER
    if ( $line =~ /BOX|CYLINDER/ ) {

        chomp $line; # remove newline if exist

        my @captured_lines; # create a empty work space

        push @captured_lines, $line; # first store BOX or CYLINDER

        # we know the next two lines belongs with BOX or CYLINDER
        # let's get them
        foreach (1..2) {
            my $extra_line = <$fh>;
            chomp $extra_line;
            push @captured_lines, $extra_line;
        }

        # manipulate the strings
        $captured_lines[0] =~ s/(\w+)/_\u\L$1/g; # convert BOX into _Box and
                                                 # CYLINDER into _Cylinder
        $captured_lines[1] =~ s/ /,/g; # convert the spaces to `,' for
                                       # the first line after match

        print join (" ", @captured_lines) . "\n"; # display processed block
    }

    # optional: stop reading the file after manipulating CYLINDER
    if ( $line =~ /CYLINDER/ ) { last }
}
close $fh;
1 Like