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.

4
  • What didn't work? Also note that you can my @lines = <$handle>; and print {$handle} @reordered;. Commented Feb 19, 2019 at 12:38
  • Possible duplicate of What’s the best way to shuffle an array in Perl? Commented Feb 19, 2019 at 13:10
  • What exactly is your question? Commented Feb 19, 2019 at 13:23
  • Checking your unlink and rename calls for failure might be informative. Commented Feb 19, 2019 at 13:29

2 Answers 2

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.)

Sign up to request clarification or add additional context in comments.

1 Comment

perl -i shuffle_file data.txt
-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; 

3 Comments

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 from the documentation of Tie::File The file is not loaded into memory, so this will work even for gigantic files.
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).

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.