使用perl中的管道对文件进行排序

时间:2015-03-17 12:33:08

标签: perl pipe

我正在寻找一种使用管道对文件进行排序的方法。我在网上查了不同的例子,但我仍然感到困惑

假设我有一个名为“perlRocks.txt”的文件,其中包含我想要排序的不同名称。

这是我到目前为止所做的:

open(SORT, "| sort>perlRocks.txt") or die "Can't sort";
close (SORT);

我错过了什么?

3 个答案:

答案 0 :(得分:1)

无需使用管道,请改用system

system("sort perlRocks.txt");

这将调用系统命令sort并将其作为参数perlRocks.txt。您将在调用脚本的shell中看到sort的输出。

当然,仅使用此命令,将显示已排序的内容,然后将其忘记。这可能是也可能不是你的想法。如果要永久存储已排序的行,则需要将输出重定向到另一个文件。

当然,perl附带了自己的sort运算符,因此您不必使用外部排序命令:sort @lines。要将文件内容添加到@lines,您可能需要使用模块File::Slurp

use warnings;
use strict;
use File::Slurp;

my @lines = read_file('perlRocks.txt');

print sort @lines;

答案 1 :(得分:1)

这不是使用perl进行排序。要在perl中执行此操作,您需要:

open ( my $input_fh, "<", "perlRocks.txt" ) or die $!;
my @lines = <$input_fh>;
print sort @lines;

您正在尝试调用命令sort

答案 2 :(得分:0)

你正在打开写作的管道。如果您已有此文件,则可能需要对已读取的内容进行排序。请参阅下面的$in示例。如果您想从脚本中写一些内容,请参阅下面的$out示例。有关更多变体,请参阅open文档。要对现有文件进行排序,您必须写入新文件然后重命名。最好使用一些shell来完成这项任务。

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

输出管道有更安全的版本,可以避免FILE_NAME_OUT内容的shell解释问题(你可以转义这个内容,但是......不。)

open my $out, '|-' or do {
    close STDOUT;
    open STDOUT, '>', FILE_NAME_OUT;
    exec 'sort' or die $!;
};

如果你坚持不想使用shell,你可以使用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 );

注意FILE_NAME_INFILE_NAME_OUT可以相同,但无论如何都不是就地排序。在某些时候,光盘上有两个版本的文件,即使有一个版本可以被隐藏和无法访问。这类任务还有很好的IPC::Run模块。