1

I have a text file and i want shuffle the lines using the Perl Script. I kept the whole file into array and used shuffle in util and i want to write that shuffled data into anther file and renamed it as the old file name.

I wrote the piece of code:

use List::Util qw(shuffle);
my @lines;
my @reordered;
my $filepath1 ="C:/Users/SravanthiBekkam/Desktop/pearl/data.txt";
my $filepath2 ="C:/Users/SravanthiBekkam/Desktop/pearl/temp.txt";
my $fhandle; 
my $handle;
open ( $fhandle, "<", $filepath);

while (<$fhandle>) {

    push(  @lines, $_);
}
@reordered = shuffle(@lines);
open ( $handle, ">", $filepath2);
foreach  (@reordered) {
    print $handle  "$_\n";
}
close $fhandle;
close $handle;
unlink $fhandle;
rename($handle, $fhandle);

In the above code I stored the file into the @lines array and shuffled the array and rewriting into the another file and am removing the previous file and renaming the appended file as original file.

Expected to shuffle the lines in a same file or write into another at least.

simbabque
  • 53,749
  • 8
  • 73
  • 136
sravs
  • 61
  • 3

2 Answers2

2

This is a great example of a program that gets a lot shorter if you a) use more Perlish idioms and b) make use of I/O indirection to get rid of all that opening and reading files.

use List::Util qw(shuffle);

print shuffle <>;

This reads a file from STDIN and writes a shuffled version to STDOUT. So, if it was in a file called shuffle_file, you could call it like this:

$ shuffle_file < data.txt > temp.txt

Of course, you'd need to then do the renaming yourself. But that seems a small price to pay for not having to write all that tedious extra code :-)

Oh, and I think the problem with your original code is that you're calling rename() passing it closed filehandles - when it requires filenames.

rename($filepath2, $filepath1);

(There also seems to be some confusion over the name of $filepath1 - sometimes you just call it $filepath.)

Dave Cross
  • 68,119
  • 3
  • 51
  • 97
-1

You can use the Tie::File module. This lets you access the contents of a file as an array.

use List::Util qw(shuffle);
use Tie::File;

tie my @lines, 'Tie::File', "C:/Users/SravanthiBekkam/Desktop/pearl/data.txt";
@lines = shuffle @lines;
untie @lines;
JGNI
  • 3,933
  • 11
  • 21
  • 2
    Is this a comment or an answer? /// Tie::File is NEVER the answer, especially here. It'll just make your program crazy slow and make it gobble up oodles memory for nothing, because your version is no shorter than a version that uses File::Slurper. – ikegami Feb 19 '19 at 13:27
  • @ikegami from the documentation of Tie::File The file is not loaded into memory, so this will work even for gigantic files. – JGNI Feb 19 '19 at 13:38
  • No, it won't. On top of the fixed-size buffer, Tie::File keeps an index of every line it encounters. This takes 28 bytes per line on a 64-bit build of Perl (not counting the memory allocator's overhead). If the average line is short (e.g. computer code), visiting every line as in your post will cause Tie::File to actually use up more memory than loading the file into a scalar! Even if the lines are long, we're still talking about a prohibitively gigantic amount of memory for gigantic files. All while taking 30x longer (for some tasks, including trivial ones). – ikegami Feb 19 '19 at 13:48