Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Mike Lewis on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Removing first and last line of text file 1

Status
Not open for further replies.

cheguvera

Programmer
Oct 13, 2005
32
0
0
GB
Hi All,

My requirement is, I want to remove first and last line of a text file.

I did it like,

###################################################
open READ_FILE ; # This is file I am reading
open WRITE_FILE ; # This is file I am writting

$cur_lino = 0 ;
$prev_lino = 0 ;
$prev_line = "" ;

while (<READ_FILE>)
{
$cur_lino ++ ;
if ( $prev_lino > 1 )
{ print WRITE_FILE $prev_line ; }
$prev_line = $_ ;
$prev_lino ++ ;
}

close READ_FILE ;
close WRITE_FILE ;
###################################################

This works.
But, is there a better way to do this? any ready utility?command?
Also, I am on Unix, but do not want to use shell commands in perl i.e. $var1 = `wc -l $filename`. Don't want to do this.

Thanks in advance.
 
I'm curious, what does
Code:
$cur_lino ++ ;
do?

"In complete darkness we are all the same, only our knowledge and wisdom separates us, don't let your eyes deceive you.
 
Hi 1DMF,

You are right. $cur_lino ++ does nothing.
When I wrote the script for the first time, there was some other logic, which I removed. That line is just there because I have not deleted it, please ignore it.

Thanks
 
well apart from that i see nothing wrong with your code, why do you want to change it? if it aint broke!

"In complete darkness we are all the same, only our knowledge and wisdom separates us, don't let your eyes deceive you.
 
Hi,

This 3-4 line code does my job for now.

But its not a very generic thing. Say, I get a requirement that, I have to remove top 3 and bottom 2 lines of a file. Or, depending on the contents of file, the lines I need to chop is going to change etc etc
Just out of interest I want to explore if there is a better, more "Perly" way to do this. Or is there a module for this?

Regards
 
well 1stly i'd say this is PERLY! , the beauty of perl is many ways to skin a cat and you are using perfectly good syntax, which is why it works :)

the difficulty with your process is that it is 'AFAIK' not possible to know how many lines are in a flat text file, before processing it so , if you want a function/routine to give you fexability, it can be done, but rather than shrinking your code, it would expand it. is that ok with you?

"In complete darkness we are all the same, only our knowledge and wisdom separates us, don't let your eyes deceive you.
 
Code:
use strict;
use warnings;

my $from = shift;
my $to = shift;

my @data = (<>);

print splice $data, $from, scalar @data - $from - $to;
might do the trick.
Code:
./myscript 5 25 input.txt

Steve

[small]"Every program can be reduced by one instruction, and every program has at least one bug. Therefore, any program can be reduced to one instruction which doesn't work." (Object::perlDesignPatterns)[/small]
 
well i've had a quick think and came up with this, i've not tested it, so it may need tweaking but it should give you food for thought..
Code:
sub make_file {

#_[0] = source file
#_[1] = target file
#_[2] = top excludes
#_[3] = bottom excludes

# Set Vars
my $src_file = $_[0];
my $trg_file = $_[1];
my @top = split(/,/, $_[2]);
my @bot = split(/,/, $_[3]);
my %top = map {$_,$_} @top;
my $cnt = 0;

# Read Source File
open (READ_FILE,$src_file);
my @src = <READ_FILE>;
close(READ_FILE);

# Loop bottom excludes and set relative to number of lines in source file
for(@bot){
    my $num = @src - $_;
    $_ = $num;
}

# set hash of bottom excludes
my %bot = map {$_,$_} @bot;

# open target file and create output.
open(WRITE_FILE , ">$trg_file");
    for(@src){
        $cnt++;
        if(!exists($top->{$cnt}) && !exists($bot->{$cnt})){
             print WRITE_FILE $_;
        }

    }
close (WRITE_FILE);

}

you would call it simply
Code:
&make_file("source_file","target_file","1,3,5","1,2,3");

this would remove the 1st , 3rd and 5th top lines and the bottom 3!

"In complete darkness we are all the same, only our knowledge and wisdom separates us, don't let your eyes deceive you.
 
Apologies, should have been
Code:
print splice [red]@[/red]data, $from, scalar @data - $from - $to;
My bad...

And of course you'd need a bit of error checking, e.g. that $from + $to is not greater than the number of lines in the file [smile]

Steve

[small]"Every program can be reduced by one instruction, and every program has at least one bug. Therefore, any program can be reduced to one instruction which doesn't work." (Object::perlDesignPatterns)[/small]
 
lol - I kept thinking i'm sure a splice could do the job, but didn't know the syntax - good one Steve

"In complete darkness we are all the same, only our knowledge and wisdom separates us, don't let your eyes deceive you.
 
This type of thing is easily done with the Tie::File module.

Code:
use Tie::File;
tie my @array, 'Tie::File', 'file.txt' or die "$!";
shift @array;
pop @array;
untie @array;

You may also need to use the Fcntl module if file locking is an issue.



- Kevin, perl coder unexceptional!
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top