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

Hello monks,

I'm using the following code to remove new line characters from the end of a data file.

#!/perl/bin/perl.exe -w use strict; use vars qw($cur_pos $buf); my $file = $ARGV[0]; open my $fh, "+<$file" or die "$!"; my $size = 4096; seek $fh, -$size, 2; while (1) { $cur_pos = tell $fh; read $fh, $buf, $size; last if $buf =~ m/\S/s; seek $fh, -$size*2, 1; } $buf =~ m/(\s*)$/s; $cur_pos += $-[0] || 0; truncate $fh, ++$cur_pos if $cur_pos; close $fh;
And this is what I'm using for a data file
0x130002a; 12.23.34.45; 0x2c60021; RstoneSwRtr 0x130009d; 12.23.34.45; 0x3c6000e; LucentP550R 0x13000fa; 1.2.3.4; 0x21000c; Rtr_Cisco 0x130012e; 1.2.3.4; 0x21000c; Rtr_Cisco 0x1300183; 1.2.3.4; 0x21b001d; 6H262_18 0x13001a8; 1.2.3.4; 0x2c60021; RstoneSwRtr 0x13001f9; 1.2.3.4; 0x21000c; Rtr_Cisco

The problem is that truncate is removing everything from the underscore in Rtr_Cisco down instead of leaving Rtr_Cisco intact.

data file looks like this after truncated

0x130002a; 12.23.34.45; 0x2c60021; RstoneSwRtr 0x130009d; 12.23.34.45; 0x3c6000e; LucentP550R 0x13000fa; 1.2.3.4; 0x21000c; Rtr_Cisco 0x130012e; 1.2.3.4; 0x21000c; Rtr_Cisco 0x1300183; 1.2.3.4; 0x21b001d; 6H262_18 0x13001a8; 1.2.3.4; 0x2c60021; RstoneSwRtr 0x13001f9; 1.2.3.4; 0x21000c; Rtr_
Does anyone have any idea whats going wrong?
Thanks

Replies are listed 'Best First'.
Re: File Truncation Problem
by jmcnamara (Monsignor) on Dec 13, 2002 at 14:38 UTC

    I tried this on Linux and it behaved as expected.

    In fact I unit tested this for variety of cases when I posted it here based on PrakashK's solution. ;-)

    As such the problem probably arises from the fact that the Dos newlines are being converted to "\n" when they are read. Try to binmode() the file handle and run the program again.

    open my $fh, "+<$file" or die "$!"; binmode $fh; ...

    --
    John.

      Thanks for the code jmcnamara.
Re: File Truncation Problem
by Orsmo (Beadle) on Dec 13, 2002 at 14:36 UTC
    If you are really just trying to match newlines, then why not:
    $buf =~ m/(\n*)$/s;
    Further, you don't seem to be using the submatch at all, so you could drop the parens:
    $buf =~ m/\n*$/s;
    But I'm just doing this by sight. I haven't tested to be sure.