Rohith Prasad K M
Rohith Prasad K M

Reputation: 27

perl script for removing the characters and lines below it

PIN W[2]
DIRECTION INPUT ;
USE SIGNAL ;
PORT
LAYER M5
        RECT 0.115 0.59 0.175 1.22 ;
        RECT 0.06 0.98 0.175 1.22 ;
        RECT 0.335 1.16 0.395 1.44 ;
        RECT 0.51 0.57 0.63 0.65 ;
LAYER M3
        RECT 0.115 0.59 0.175 1.22 ;
        RECT 0.06 0.98 0.175 1.22 ;
        RECT 0.335 1.16 0.395 1.44 ;
        RECT 0.51 0.57 0.63 0.65 ;
LAYER M1
        RECT 0.115 0.59 0.175 1.22 ;
        RECT 0.06 0.98 0.175 1.22 ;
        RECT 0.335 1.16 0.395 1.44 ;
        RECT 0.51 0.57 0.63 0.65 ;
LAYER M6
        RECT 0.115 0.59 0.175 1.22 ;
        RECT 0.06 0.98 0.175 1.22 ;
        RECT 0.335 1.16 0.395 1.44 ;
        RECT 0.51 0.57 0.63 0.65 ;
END
END W[2]

What I wanted is to search for the number starting with LAYER M (having greatest number in the above) and print only the lines starting with RECT below it. Please refer the below snippet for how the required lines should look like.

PIN W[2]
DIRECTION INPUT ;
USE SIGNAL ;
PORT
LAYER M6
        RECT 0.115 0.59 0.175 1.22 ;
        RECT 0.06 0.98 0.175 1.22 ;
        RECT 0.335 1.16 0.395 1.44 ;
        RECT 0.51 0.57 0.63 0.65 ;
END
END W[2]

Upvotes: 1

Views: 110

Answers (2)

bytepusher
bytepusher

Reputation: 1578

I find it easier to not step through the file twice, and line numbers tend to confuse me, so I've decided to post my take on it.

Good luck and feel free to comment any improvements to edit in!

#!/usr/bin/env perl
use strict;
use warnings;

open my $fh, '<', 'input.txt' or die "Cannot open file < '$input_fn': $!";

my %layers;

my $layer_number;

my ( $begin_block, $end_block );

while ( my $line = <$fh> ){

    if ( $line =~ /^[\s\t]*LAYER\s+M([0-9]+)/ ){
        $layer_number = $1;
    }

    # layer number not set: Add to begin block
    unless ( $layer_number ){
        $begin_block .= $line;
        next;
    }

    # END: no further layers. Just slurp it and done.
    if ( $line =~ /END/ ){
        my $slurped_end = do{ local $/; <$fh>; };
        $end_block = $line . $slurped_end;
        last;
    }

    # store line for this block
    $layers{ $layer_number } .= $line;
}

close $fh;

# find highest block, reassemble and print
my $highest_block_number = ( sort{ $a <=> $b } keys %layers )[-1];

print $begin_block . $layers{ $highest_block_number } . $end_block;

Upvotes: 2

H&#229;kon H&#230;gland
H&#229;kon H&#230;gland

Reputation: 40778

Here is an example. It scans the lines of the file file.txt twice. The first time it records the maximum layer number, and the second time it prints lines if it is not a layer, or if it is the maximum layer block:

use strict;
use warnings;

my $fn = 'file.txt';
my @lines;
my $max_layer_num = 0;
open ( my $fh, '<', $fn ) or die "Could not open file '$fn': $!";
while (<$fh>) {
    push @lines, $_;
    if ( /^LAYER\s+M(\d+)/ ) {
        $max_layer_num = $1 if $1 > $max_layer_num;
    }
}
close $fh;
my $i = 0;
while ( $i <= $#lines ) {
    $_ = $lines[$i];
    if( /^LAYER\s+M(\d+)/ ) {
        if ( $1 != $max_layer_num ) {
            while (1) {
                $i++;
                last if $i > $#lines;
                $_ = $lines[$i];
                last if $_ !~ /^\s+RECT/;
            }
            next;
        }
    }
    print; $i++
}

Upvotes: 1

Related Questions