Reputation: 603
I am looking for a way to sort a file using pipe. I have checked different examples online but I am still confused
Let's say I have a file called "perlRocks.txt" with different names I want to sort.
This is what I have so far:
open(SORT, "| sort>perlRocks.txt") or die "Can't sort";
close (SORT);
What am I missing?
Upvotes: 1
Views: 1358
Reputation: 26121
You are opening pipe for writing. If you already have this file you probably want read content sorted. See the example with $in
below. If you want to write something from your script instead see example with $out
below. See open
documentation for more variants. For sorting existing file, you have to write to a new file and then rename. It's best to use some shell for this task.
use strict;
use warnings;
use autodie;
use constant FILE_NAME_IN => 'perlRocks.in';
use constant FILE_NAME_OUT => 'perlRocks.out';
open my $in, '-|', 'sort', FILE_NAME_IN;
while (<$in>) {print};
open my $out, '|-', "sort >'@{[FILE_NAME_OUT]}'";
print $out $_, "\n" for qw(foo bar baz quux);
There is safer version for output pipe which avoids problems with shell interpretation of FILE_NAME_OUT content (You can escape this content but ... no.)
open my $out, '|-' or do {
close STDOUT;
open STDOUT, '>', FILE_NAME_OUT;
exec 'sort' or die $!;
};
If you insist you don't want to use shell, you can use Perl.
use strict;
use warnings;
use autodie;
use constant FILE_NAME_IN => 'perlRocks.txt';
use constant FILE_NAME_OUT => 'perlRocks.txt';
# don't bother with fork if you don't want continue with Perl process
my $pid = fork;
die "cannot fork" unless defined $pid;
unless ($pid) { # use just this code inside in this case
close STDIN;
close STDOUT;
open STDIN, '<', FILE_NAME_IN;
unlink FILE_NAME_IN if FILE_NAME_IN eq FILE_NAME_OUT;
open STDOUT, '>', FILE_NAME_OUT;
exec 'sort' or die $!;
}
waitpid( $pid, 0 );
Note FILE_NAME_IN
and FILE_NAME_OUT
can be same, but it is not in-place sorting anyway. There are both versions of the file at the disc in some time even one can be hidden and inaccessible. There is also good IPC::Run module for this sort of tasks.
Upvotes: 0
Reputation: 40499
There is no need to use a pipe, use system
instead:
system("sort perlRocks.txt");
This will invoke the system command sort
and give it perlRocks.txt
as parameter. You will see the output of sort
in the shell from which you invoked your script.
Of course, with just this command, the sorted content will be shown and then be forgotten. This might or might not what you have in mind. If you want to permanently store the sorted lines you need to redirect the output into another file.
Of course, perl comes with its own sort operator, so that you don't have to use an external sort command: sort @lines
. In order to get the content of your file into @lines
, you might want to use the module File::Slurp
:
use warnings;
use strict;
use File::Slurp;
my @lines = read_file('perlRocks.txt');
print sort @lines;
Upvotes: 1
Reputation: 53478
This isn't using perl to sort. To do this in perl, you would want to:
open ( my $input_fh, "<", "perlRocks.txt" ) or die $!;
my @lines = <$input_fh>;
print sort @lines;
What you're doing is trying to call the command sort
.
Upvotes: 1