Beefy Boxes and Bandwidth Generously Provided by pair Networks
Clear questions and runnable code
get the best and fastest answer
 
PerlMonks  

printing specific lines

by Anonymous Monk
on Feb 27, 2005 at 20:55 UTC ( [id://434920]=perlquestion: print w/replies, xml ) Need Help??

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

Hi, i need to print specific lines from a file. The lines to be printed are stored in a separte file
1 3 5 7
open (OUT, ">gout"); while (<>){ chomp; $line = $_; push @array, $line; } print @array; open (IN, "<grep"); while (<IN>){ if ($. == ???) {print OUT $_} }
thanks

Replies are listed 'Best First'.
Re: printing specific lines
by esskar (Deacon) on Feb 27, 2005 at 21:10 UTC
    as i understand: store the line number in a hash instead, so
    my %lines = map { ($_, 1) } qw/1 3 5 7/; open(IN, "<grep") or die; while (<IN>) { print OUT $_ if $lines{$.}; }
    HTH
Re: printing specific lines
by traveler (Parson) on Feb 27, 2005 at 21:22 UTC
    If the text file could be large, consider
    open (IN, "<grep"); my %lines; while (<IN>){ $lines{$_} = 1; } close IN; open (OUT, ">gout"); # assumes input data comes from stdin while (<>){ print OUT $_ if exists $lines{$.}; } close OUT;
    Untested, but I think I got it right. Save the small stuff, not the big stuff.
Re: printing specific lines
by ambrus (Abbot) on Feb 27, 2005 at 22:13 UTC

    I don't use perl for things for which there are standard unix utils.

    $ cat text first second third fourth fifth sixth seventh eighth $ cat nums 1 4 6 7 $ ed -s text < nums first fourth sixth seventh

    Update: this sucks if the text file is too large to load in memory. In that case,

    Update: here's a perl solution too:

    perl -we 'open N, "<", shift or die; $p = 0; while(defined($n = <N>)) +{ $s = <> for $p + 1 .. $n + 0; print $s; $p = $n; }' nums text

    Update: if anyoune knows how to convert the above snippet so that it uses either $. or IO::Handle::input_line_number, please reply me, cause I can't figure out how to do that.

Re: printing specific lines
by dmorelli (Scribe) on Feb 28, 2005 at 03:48 UTC
    I'm surprised nobody mentioned using Tie::File so you can use the numeric values as array indices.

    #! /usr/bin/perl -w use strict; use Fcntl 'O_RDONLY'; use Tie::File; # Path to file containing lines as arg my $linesPath = shift; # Tie the file read-only, if you want to read only, to be safe tie my @linesFile, 'Tie::File', $linesPath, mode => O_RDONLY or die "Can't open file $linesPath: $!"; while(<DATA>) { chomp; # $_ - 1, I'm assuming that the list isn't 0-based print "$linesFile[$_ - 1]\n"; } untie @linesFile; __DATA__ 1 3 4 7
Re: printing specific lines
by thedoe (Monk) on Feb 27, 2005 at 21:04 UTC
    I'm sorry, but I don't understand your question. Are the 1 3 5 7 the line numbers you want to print or are they the actual lines in a file? What is the output file you are are writing to, are you trying to print out to that file or STDOUT?
      the line numbers to print are stored in a file.
      1 3 5
      text file
      once upon a time ... big bear .... shot dead
      so the lines i want to print are 1 3 and 5, to a separate output file thanks
Re: printing specific lines
by Anonymous Monk on Feb 27, 2005 at 21:03 UTC
    i was perhaps thinking
    open (OUT, ">gout"); while (<>){ chomp; $line = $_; push @array, $line; } print @array; open (IN, "<grep"); while (<IN>){ next unless $. == $array[$i++]; print OUT $_; #if ($. == @array) {print OUT $_} }

      This code has a well-hidden bug (or maybe I'm too tired): you always increment $i even if the equalty doesn't stand. Change

      next unless $. == $array[$i++];
      to
      next unless $. == $array[$i]; $i++;
      and it should work.

      Also, you should really add or die "open: $! to your open statement.

      Update: and to eliminate a warning, you may want to replace

      next unless $. == $array[$i++]; print OUT $_;
      to
      next unless $. == $array[$i]; print $_; ++$i < @array or last;
Re: printing specific lines
by merlyn (Sage) on Feb 27, 2005 at 21:24 UTC

      Anonymous Monk gives some code he's started so you are a bit unfair I think.

        As someone who creates exercises for a living, this is exactly the kind of exercise I would create. I also note the absence of "real world" indicators in the question, again leading toward an abstract problem that someone would not have occur "in the wild".

        No, I'll stand by my assessment. Homework, with some of the work done, but missing some essential piece. Nothing that should be answered, because the student should go back to the teacher for answers, not rely on the virtual brain of the monastery.

        -- Randal L. Schwartz, Perl hacker
        Be sure to read my standard disclaimer if this is a reply.

Re: printing specific lines
by TedPride (Priest) on Feb 28, 2005 at 06:17 UTC
    use strict; my ($handle, @lines, $c); open($handle, "lines"); @lines = <$handle>; close($handle); chomp @lines; @lines = sort {$a <=> $b} @lines; open($handle, "text"); while ($c <= $#lines) { <$handle> for (($.)..($lines[$c++]-2)); print $_ = <$handle>; } close($handle);
    This assumes that line 1 is considered the first line, not the second. It allows for line numbers given out of order, and doesn't require reading the entire text into memory at once.
Re: printing specific lines
by chas (Priest) on Feb 27, 2005 at 21:22 UTC
    You could, for example, make a hash with keys equal to the line numbers you want to print (and corresponding true values) and use this to check whether a line should be printed as you loop.
    (Update:Sorry, didn't see that this had been suggested.)
    Are you collecting the line numbers from STDIN? (That's what it seems to be.) In that case, what does the "separate file" have to do with your code?
    chas
    (Update: Rewrote to fix error.)
Re: printing specific lines
by Random_Walk (Prior) on Feb 28, 2005 at 15:32 UTC

    Just for fun.....

    #!/usr/bin/perl use warnings; use strict; my @prints; while (<DATA>) { chomp; $prints[--$_]="print this one"; } open IN, '<', 'grep' or die 'dulce et decorum est'; open OUT, '>', 'gout' or die 'dulce et decorum est'; while (<>) { print OUT if shift @prints } close IN; close OUT; __DATA__ 1 3 5 8

    Cheers,
    R.

    Pereant, qui ante nos nostra dixerunt!

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://434920]
Approved by Corion
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others learning in the Monastery: (5)
As of 2024-04-25 08:43 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found