in reply to Re^2: How do I move two lines up in a file using perl
in thread How do I move two lines up in a file using perl

use strict; use warnings; open (my $fh, '<', '/usr/share/dict/words') or die "Unable to open wor +ds: $!"; while (1) { my $line = <$fh>; if ( $line =~ /^M....$/) { my $pos = tell($fh) - length($line); chomp $line; print "$line found\n"; # Go back to beginning of file (rewind) seek ($fh,0,0); # Now go and read that record again seek ($fh, $pos, 0); $line = <$fh>; chomp $line; print "$line found again!\n"; last; } } close ($fh);
Update: Also note that the offset can be negative releative to the current file position, see seek.

Replies are listed 'Best First'.
Re^4: How do I move two lines up in a file using perl
by 7stud (Deacon) on Mar 17, 2010 at 09:29 UTC

    Is that second seek() really going to work on windows? Suppose on windows you have these lines in a text file:

    22\r\n 4444\r\n 333\r\n

    After reading the second line, I think tell() will report the file position as 10:

    01 2 34567 8 90 22\r\n4444\r\n

    And the length of the second line as reported by length($line) in your code will be 5: when reading a line from a file, perl automatically converts the actual newline found in the file(in this case \r\n) to \n, so $line will be assigned "4444\n", and length($line) will be 5. So $pos = 10 - 5 = 5. Then seeking to position 5 in the file will land you here:

    22\r\n 4444\r\n ^ file pointer

    ...which is not the start of the line. Can anyone test that on windows?

    Using seek() to move to the beginning or end of the file will work because those are absolute positions--but doing a relative seek() won't work because counting the length of a line with a perl program does not give you the actual length of the line in the file. To do relative seeks, you need to turn off the automatic newline conversions that occur while reading a file by using something like binmode().