tags:

views:

76

answers:

5

I have a source text in a file and looking for a code that would take the second (or n-th - in general) row from this file and print to a seperate file.

Any idea how to do this?

A: 

You could always:

  1. Read all of the file in and but it into one variable.
  2. Split the variable at the newline and store in an array
  3. Write the value at the index 1 (for the second row) or the n-1 position to the separate file
Kyra
A: 

I think this will do what you want:

line_transfer_script.pl:

open(READFILE, "<file_to_read_from.txt");
open(WRITEFILE, ">File_to_write_to.txt");

my $line_to_print = $ARGV[0]; // you can set this to whatever you want, just pass the line you want transferred in as the first argument to the script
my $current_line_counter = 0;

while( my $current_line = <READFILE> ) {
  if( $current_line_counter == $line_to_print ) {
     print WRITEFILE $current_line;
  }

  $current_line_counter++;
}

close(WRITEFILE);
close(READFILE);

Then you'd call it like: perl line_transfer_script.pl 2 and that would write the 2nd line from file_to_read_from.txt into file_to_write_to.txt.

coffeepac
You should always use lexical filehandles, and keeping track of the line number manually is clumsy and unnecessary in Perl.
Ether
Also use 3 arg open. 2 arg open has problems.
xenoterracide
A: 
my $content = `tail -n +$line $input`;

open OUTPUT, ">$output" or die $!;
print OUTPUT $content;
close OUTPUT;
Vincent Robert
use lexical file handles and 3 arg open
xenoterracide
+5  A: 

You can do this natively in Perl with the flip-flop operator and the special variable $. (used internally by ..), which contains the current line number:

# prints lines 3 to 8 inclusive from stdin:
while (<>)
{
    print if 3 .. 8;
}

Or from the command line:

perl -wne'print if 3 .. 8' < filename.txt >> output.txt

You can also do this without Perl with: head -n3 filename.txt | tail -n1 >> output.txt

Ether
+1, so perlish.
M42
so if you wanted just the second line, you could replace the line with the flip-flop operator with: print if 2 .. 2or print if ($. == 2)yeah?
coffeepac
@coffeepac: correct!
Ether
@Ether: hooray! thanks!
coffeepac
A: 

use like this script.pl > outfile (or >> outfile for append)

this uses lexical filehandles and 3 arg open which are preferred to global filehandles and 2 arg open.

#!/usr/bin/perl
use strict;
use warnings;
use English qw( -no_match_vars );
use Carp qw( croak );

my ( $fn, $line_num ) = @ARGV;

open ( my $in_fh, '<', "$fn" ) or croak "Can't open '$fn': $OS_ERROR";

while ( my $line  = <$in_fh> ) {
    if ( $INPUT_LINE_NUMBER == $line_num ) {
        print "$line";
    }
}

note: $INPUT_LINE_NUMBER == $.

here's a slightly improved version that handles arbitrary amounts of line numbers and prints to a file.

script.pl <infile> <outfile> <num1> <num2> <num3> ...

#!/usr/bin/perl
use strict;
use warnings;
use English qw( -no_match_vars );
use Carp qw( croak );
use List::MoreUtils qw( any );

my ( $ifn, $ofn, @line_nums ) = @ARGV;

open ( my $in_fh , '<', "$ifn" ) or croak "can't open '$ifn': $OS_ERROR";
open ( my $out_fh, '>', "$ofn" ) or croak "can't open '$ofn': $OS_ERROR";

while ( my $line  = <$in_fh> ) {
    if ( any { $INPUT_LINE_NUMBER eq $_ } @line_nums ) {
        print { $out_fh } "$line";
    }
}
xenoterracide