http://www.perlmonks.org?node_id=1125789

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

Hi all,

i have a text file that contains the following lines

High fanout nets in the post compile netlist: Fanout Type Name -------------------------- 2 INT_NET Net : c_c Driver: c_pad 2 INT_NET Net : b_c Driver: b_pad 2 INT_NET Net : a_c Driver: a_pad 1 INT_NET Net : sum_c Driver: sum_1_SUM0_0 1 INT_NET Net : N_5 Driver: sum_1_CO0_i

I have to write a perl script that saves the following statements only, i.e. high fanout nets alone. For that, if i write a script which find maximum number in my text file and copies those statements in new file, it will copy the following statements.

2 INT_NET Net : c_c 2 INT_NET Net : b_c 2 INT_NET Net : a_c

Here is the code i tried, but could not get the text file as i wish....

my $high_number = 0; open (F1, "<new.txt") or die "cant open it$!"; while (<F1>) { my ($number) = m/:(\d+):/; $high_number = $number if $number > $high_number; } print "Highest number found = $high_number\n"; close (F1);

please help me out in this, thank you all....

Replies are listed 'Best First'.
Re: Find maximum number in text file and copying its full statement in new text file?
by Athanasius (Archbishop) on May 06, 2015 at 03:18 UTC

    Hello sumathigokul,

    Your regex m/:(\d+):/ finds a sequence of one or more digits occuring anywhere in the line between two colon characters. But in the text file shown, the only colons occur later in the line. You need something like this:

    while (<F1>) { my ($number) = /^\s*(\d+)/; if (defined $number) { $high_number = $number if $number > $high_number; } }

    in which the regex finds a sequence of digits at the beginning of the line, preceeded by zero or more whitespace characters only. Note also that if a match fails (as it does for lines 1, 2, 3, 5, 7, etc.), the variable $number is undefined. Always begin your scripts with:

    use strict; use warnings;

    In this case warnings will alert you to the fact that $number is being used in a numerical comparison when it is undef.

    Hope that helps,

    Athanasius <°(((><contra mundum Iustus alius egestas vitae, eros Piratica,

Re: Find maximum number in text file and copying its full statement in new text file?
by kcott (Archbishop) on May 06, 2015 at 04:02 UTC

    G'day sumathigokul,

    Your regex baffles me! You're trying to match (and capture) one or more digits immediately preceded by and followed with a colon — clearly not what you want. I'd recommend spending some time with the Perl Regular Expressions Tutorial.

    You have no code to output the wanted lines — which is why that part isn't working. Take a look at open; note how both of the initial examples (for reading and writing) use the 3-argument form and lexical filehandles; start doing this yourself.

    This code has the logic you need — you'll need to add the I/O:

    #!/usr/bin/env perl use strict; use warnings; my $re = qr{ \A \s+ ( \d+ ) }x; my $high = 0; my @lines; while (<DATA>) { /$re/ or next; my $num = $1; next if $num < $high; if ($num > $high) { $high = $num; @lines = (); } push @lines, $_; } print "Highest number: $high\n"; print @lines; __DATA__ High fanout nets in the post compile netlist: Fanout Type Name -------------------------- 2 INT_NET Net : c_c Driver: c_pad 2 INT_NET Net : b_c Driver: b_pad 2 INT_NET Net : a_c Driver: a_pad 1 INT_NET Net : sum_c Driver: sum_1_SUM0_0 1 INT_NET Net : N_5 Driver: sum_1_CO0_i

    Output:

    Highest number: 2 2 INT_NET Net : c_c 2 INT_NET Net : b_c 2 INT_NET Net : a_c

    -- Ken

      Hi kcott,

      First of all thank you for your reply and Good day to you...I have modified the code, so that it extracts the data from one file and copies those statements to new file...But, its not copying...

      use strict; use warnings; my $re = qr{ \A \s+ ( \d+ ) }x; my $high = 0; my @lines; open (F1, "<designer.log") or die ; open (F2, ">>new_lines.txt") or die; while (<F1>) { /$re/ or next; my $num = $1; next if $num < $high; if ($num > $high) { $high = $num; @lines = (); } push @lines, $_; print F2 @lines; } print "Highest number: $high\n"; close (F1); close (F2);

      Correct me if its wrong....

        If you are going to print inside the loop, then use of @lines is useless (given the code), for the current line would be the only one (1) element of @lines, ever.

        What is your input? What is the highest number printed?

Re: Find maximum number in text file and copying its full statement in new text file?
by aaron_baugher (Curate) on May 06, 2015 at 04:00 UTC

    This loops through the lines, getting the Fanout value from the lines with INT_NET, and if it's equal to or greater than the maximum Fanout value so far, it saves that line along with its Fanout value as a 2-element array reference in the array @lines.

    Once it's done, it has the largest Fanout value in $max and all the lines with that value (along with some other lines, possibly) as the first elements in the array @lines. The map/grep statement goes through those, grepping for the ones with the $max Fanout value and then using map to pull out the line itself and pass that to print.

    #!/usr/bin/env perl use 5.010; use warnings; use strict; my $max = 0; my @lines; # 2D array, each element holding a line and its Fanout val +ue while (<DATA>){ if (/(\d+)\s+INT_NET/ and $1 >= $max ){ push @lines, [$_,$1]; $max = $1; } } print for map { $_->[0] } grep { $_->[1] == $max } @lines; __DATA__ Fanout Type Name -------------------------- 2 INT_NET Net : c_c Driver: c_pad 2 INT_NET Net : b_c Driver: b_pad 2 INT_NET Net : a_c Driver: a_pad 1 INT_NET Net : sum_c Driver: sum_1_SUM0_0 1 INT_NET Net : N_5 Driver: sum_1_CO0_i

    Aaron B.
    Available for small or large Perl jobs and *nix system administration; see my home node.

Re: Find maximum number in text file and copying its full statement in new text file?
by jeffa (Bishop) on May 06, 2015 at 16:22 UTC

    This "way to do it" uses a hash to find the highest number:

    use strict; use warnings; my %candidates; while (<DATA>) { push @{$candidates{$1}}, $_ if /^\s+(\d+)/; } my ($highest) = sort {$b<=>$a} keys %candidates; print for @{ $candidates{$highest} }; __DATA__ High fanout nets in the post compile netlist: Fanout Type Name -------------------------- 2 INT_NET Net : c_c Driver: c_pad 2 INT_NET Net : b_c Driver: b_pad 2 INT_NET Net : a_c Driver: a_pad 1 INT_NET Net : sum_c Driver: sum_1_SUM0_0 1 INT_NET Net : N_5 Driver: sum_1_CO0_i

    jeffa

    L-LL-L--L-LL-L--L-LL-L--
    -R--R-RR-R--R-RR-R--R-RR
    B--B--B--B--B--B--B--B--
    H---H---H---H---H---H---
    (the triplet paradiddle with high-hat)