DespacitoPerl has asked for the wisdom of the Perl Monks concerning the following question:

I am developing a script, which to delete the lines in a report, if matched expression are found in waiver file, which is a filtering file. Note that report format, the first few line are different format to the lines i want to check and delete if matched in waiver file. Report file:

**************************************** Report : noise_parameters Version : K-2015.12 Date : Mon Jul 24 02:42:46 2017 **************************************** analysis mode : report_at_source ignore arrival : true include beyond Rails : true enable propagation : true analysis type : violators **************************************** Report : noise -all_violators -nosplit -low -above Version: K-2015.12 Date : Mon Jul 24 02:42:46 2017 **************************************** analysis mode: report_at_source slack type: height noise_region: above_low pin name (net name) width height slack ----------------------------------------------------- es (esg) 135.42 0.37 -0.20 es (esh) 129.19 0.38 -0.17 es (esm) 184.15 0.49 -0.14 and so on...

waiver file:

es,135.42,0.37,"Waived,by","Waived,Date","Approved,by","Approved,date +" es,129.19,0.38,,"Waived,by","Waived,Date","Approved,by","Approved,dat +e"

output:

**************************************** Report : noise_parameters Version : K-2015.12 Date : Mon Jul 24 02:42:46 2017 **************************************** analysis mode : report_at_source ignore arrival : true include beyond Rails : true enable propagation : true analysis type : violators **************************************** Report : noise -all_violators -nosplit -low -above Version: K-2015.12 Date : Mon Jul 24 02:42:46 2017 **************************************** analysis mode: report_at_source slack type: height noise_region: above_low pin name (net name) width height slack ----------------------------------------------------- es (esm) 184.15 0.49 -0.14 es (esb) 208.55 0.48 -0.13 and so on

my code is like this

#! /tools/perl/5.8.8/linux/bin/perl use strict; use warnings; use Data::Dumper; # Source script my $report = $ARGV[1] ; my $waiver = $ARGV[3] ; my $result = $ARGV[5] ; # Set up a hash to receive the information my %identifier = (); # Read the violations file into the hash open my $filter, '<', $waiver or die; while (my $vline = <$filter>) { next unless $vline =~ /\S/; #skip blank lines my ($pins2, $w2, $h2) = split /,/, $vline; $identifier{$pins2}{'w2'} = $w2; $identifier{$pins2}{'h2'} = $h2; } print Dumper \%identifier; # Read input file line by line and compare 2 files open my $input, '<', $report or die; open my $output, ">", $result or die; while (my $wline = <$input>){ my ($pins1, $nets, $w1, $h1, $slack) = split /\s+/, $wline; # delete the contents if matched if (exists $identifier{$pins1}) { if ( ($w1 == $identifier{$pins1}{'w2'}) && ($h1 <= $identifier{$pi +ns1}{'h2'}) ) { my $start = 1; } else { my $start = 0; } } else { my $start = 0; } printf $output "$wline"; next if (my $start == 0); #if ($start == 0) { # printf $output "%-44s %-24s %-8s %-8s %-8s %-1 +0s\n", $pins1, $nets1, $w1, $h1, $slack; # } } close $filter; close $input; close $output;

Replies are listed 'Best First'.
Re: Delete lines if matched expression
by roboticus (Chancellor) on Jul 26, 2017 at 03:21 UTC

    DespacitoPerl:

    Nice, but I'd work on the code formatting a bit, it's kinda funky, making it difficult to see what you're trying to do. Also, you don't want to use "my" everywhere, only when you're declaring/defining a variable. Further, if you set a default value to your variable, you only need to set it when it would change.

    So the bit you have like this:

    if (exists $identifier{$pins1}) { if ( ($w1 == $identifier{$pins1}{'w2'}) && ($h1 <= $identifier{$pi +ns1}{'h2'}) ) { my $start = 1; } else { my $start = 0; } } else { my $start = 0; } printf $output "$wline"; next if (my $start == 0);

    could easily be changed to:

    my $start = 0; if (exists $identifier{$pins1}) { if ( ($w1 == $identifier{$pins1}{'w2'}) && ($h1 <= $identifier +{$pins1}{'h2'}) ) { $start = 1; } } printf $output "$wline"; next if (my $start == 0);

    Then, seeing how it's just a chained if statement, you could further reduce it to:

    my $start = 0; if ( exists $identifier{$pins1} && ($w1 == $identifier{$pins1}{'w2'}) && ($h1 <= $identifier{$pins1}{'h2'}) ) { $start = 1; } printf $output "$wline"; next if ($start == 0);

    There are other improvements you could make.

    I might've answered your question, or I might not have, as I didn't actually see a question.

    ...roboticus

    When your only tool is a hammer, all problems look like your thumb.

      sry, but what i wish to do is to filter out whatever the pins mentioned inside the waiver file, from the input which is the report file, the condition is if the width matched, and the height in waiver file is greater or equal to the height in input report file, the pins and its following information in report file will be deleted, as a sign it is waived, but the problem now is my script didnt delete the pins and the following information, even they are matched. So anyone of you have any ideas?

        You can't have 2 hash keys as 'es' so you need a 2nd level to your %identifier hash
        eg $identifier{$pins2}{$w2} = $h2

        #! /tools/perl/5.8.8/linux/bin/perl use strict; use warnings; use Data::Dumper; # Source script my $report = $ARGV[1] || 'report.txt' ; my $waiver = $ARGV[3] || 'waiver.csv'; my $result = $ARGV[5] || 'result.txt'; # Set up a hash to receive the information my %identifier = (); # Read the violations file into the hash open my $filter, '<', $waiver or die "Could not open $waiver : $!"; while (my $vline = <$filter>) { next unless $vline =~ /\S/; #skip blank lines $vline =~ s/^\s+//; # trim leading spaces my ($pins2, $w2, $h2) = split /,/, $vline; $identifier{$pins2}{$w2} = $h2; } print Dumper \%identifier; # Read input file line by line and compare 2 files open my $input, '<', $report or die "Could not open $report : $!"; open my $output, '>', $result or die "Could not open $result : $!"; my $header = 1; while (my $wline = <$input>){ # skip checking the heading text if ($header == 1){ print $output $wline; $header = 0 if ($wline =~ /-------/); next; } # delete the contents if matched # undef is leading space my (undef,$pins1, $nets, $w1, $h1, $slack) = split /\s+/, $wline; if (exists $identifier{$pins1}{$w1} && $identifier{$pins1}{$w1} >= $h1) { # skip matched line print "DELETED $wline"; } else { print $output $wline; } } close $filter; close $input; close $output;
        poj
Re: Delete lines if matched expression
by AnomalousMonk (Archbishop) on Jul 26, 2017 at 07:01 UTC

    Further to roboticus's reply: DespacitoPerl: Also note that the conditional in a statement like
        next if (my $start == 0);
    is always true. A new lexical is created in the scope of the if-expression (update: see Update 2 below) and initialized as undefined. It does not exist outside of the if-expression. undef coerces to 0.

    c:\@Work\Perl\monks>perl -wMstrict -le "my $x = 999; print 'is it safe?' if (my $x == 0); " "my" variable $x masks earlier declaration in same scope at -e line 1. Use of uninitialized value in numeric eq (==) at -e line 1. is it safe?
    Note also that there seem to be some warnings that you are ignoring.

    Update 1: Just to be clear, this use of a lexical variable and other, similar uses of lexicals in what amount to dead scopes are all semantic errors.

    Update 2: "A new lexical is created in the scope of the if-expression ..."   This is not true. Because the if-expression in
        next if (my $start == 0);
    is a statement modifier (see perlsyn), no new scope is created. That (I finally realized) is the point of the "my" variable $x masks earlier declaration in same scope ... warning.

    c:\@Work\Perl\monks>perl -wMstrict -le "my $x = 999; print 'is it safe?' if (my $x = 1); print $x; " "my" variable $x masks earlier declaration in same scope at -e line 1. Found = in conditional, should be == at -e line 1. is it safe? 1
    The assignment causes a change in the enclosing scope, so apparently it isn't safe, Dr. Szell!

    Note that a statement of the non-statement-modifier form
        if (my $start == 0) { next; }
    would create a new scope and would eliminate one warning message.

    c:\@Work\Perl\monks>perl -wMstrict -le "my $x = 999; if (my $x = 1) { print 'is it safe?'; } print $x; " Found = in conditional, should be == at -e line 1. is it safe? 999
    Either way, however, the statement from the OPed code is still semantically problematic.

    Update 3: Added link to the Statement Modifiers section in perlsyn.


    Give a man a fish:  <%-{-{-{-<