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

HI I have a Fixed width file. I search for some pattern in that file, if that matches with any one of the lines, then that record should be placed as the first record in the file. Assume the file is Test.dat, the contents are,
ABC123
DEC456
ASD111
AAA333
BBB191
If the search string is 333, then after the process The file Test.dat should contain (333's record as the first record),
AAA333
ABC123
DEC456
ASD111
BBB191
The file will be a large file of 60MB.with 40 to 50'000 records. Any suggestion will be of great help. Thanks in advance.

Replies are listed 'Best First'.
Re: Swapping a record in a File
by rob_au (Abbot) on Dec 29, 2003 at 12:37 UTC
    For this problem, I would consider the use of Tie::File with some code similar to the following:

    use Tie::File; tie my @array, 'Tie::File', 'test.data' or die $!; for my $index (0 .. $#array) { unshift @array, splice(@array, $index, 1) if $array[$index] =~ /33 +3/; } untie @array;

     

    perl -le "print+unpack'N',pack'B32','00000000000000000000001010100010'"

Re: Swaping a record in a File
by calin (Deacon) on Dec 29, 2003 at 12:22 UTC
    Open two new files (A and B), then go through the original file line by line. If a line in the original file matches the pattern, append to file A. If not, append to file B. Finally, cat files A and B together.
Re: Swaping a record in a File
by Art_XIV (Hermit) on Dec 29, 2003 at 14:42 UTC

    Here's a brute-force way of doing it:

    use warnings; use strict; my $matching_line_loc = 0; my $matching_line = ''; open (TEST_FILE, "<test.dat") or die "Couldn't open test.dat: $!\n"; while (<TEST_FILE>) { if (/333/) { #remember matching line and line number $matching_line = $_; $matching_line_loc = $.; last; } } close TEST_FILE; if ($matching_line) { #don't bother with rest if no match! open (TEST_FILE, "<test.dat") or die "Couldn't open test.dat: $!\n"; open (TMP_FILE, ">test.tmp") or die "Couldn't open/create test.tmp: $!\n"; #print the matching line first print TMP_FILE $matching_line; #print everything BUT the matching line while (<TEST_FILE>) { print TMP_FILE $_ unless $. == $matching_line_loc; } close TMP_FILE; close TEST_FILE; #remove original file and rename rearranged file unlink "test.dat" or die "couldn't remove test.dat: $!\n"; rename "test.tmp", "test.dat"; }

    Note that this way (and others above) avoids the classic problem of 'slurping' the whole file into memory since it only deals with single lines at a time. Slurping would be pretty bad with a 60 meg file (though it would probably still work.)

    This method also assumes that there will only every be one matching line.

    Hanlon's Razor - "Never attribute to malice that which can be adequately explained by stupidity"