【问题标题】:Sort 2nd Field Descending from text file perl从文本文件 perl 降序排序第二个字段
【发布时间】:2012-11-20 17:56:40
【问题描述】:

我有一个以制表符分隔的文本文件,其格式、名称和年龄如下所示:

chris     19
bobby     29
doofus    67

我想拉入文本文件,然后通过第二个字段进行排序。我可以拉入文本文件并格式化数据,但我无法正确排序,因此删除了我拥有的排序代码......

这是简单的文件拉取:我该如何修改它?

open (FILEHERE, 'ages.txt');
while (<FILEHERE>) {
chomp;
my($n, $s) = split("\t");
print "$a\t $s";
}
close (FILEHERE);

【问题讨论】:

标签: perl sorting file-io text-files numeric


【解决方案1】:

Schwartzian transform (ST) 可以在这里提供帮助:

use strict;
use warnings;

my $data = <<END;
chris     19
doofus    67
bobby     29
END

open my $fh, '<', \$data or die $!;

print map $_->[0],
sort { $a->[1] <=> $b->[1] }
map { [ $_, /(\d+)$/ ] }
<$fh>;

close $fh;

输出:

chris     19
bobby     29
doofus    67

从 ST 的底部向上读取。该例程获取一个文件行,然后在map 中将该行放置为匿名数组的第一个元素。第二个元素是从第二列捕获的数值。 sort 采用匿名子例程对匿名数组的第二个元素进行排序(因此,取消引用箭头运算符$a-&gt;[1])。结果被传递给map 以访问已排序的行并最终打印出来。

希望这会有所帮助!

【讨论】:

  • 虽然使用内存文件是一件很棒的事情,但您可能只想为此使用DATA 文件句柄。
  • 我尝试调整它以使用 open (FILE, 'ages.txt) 或 w.e 拉入一个文件,但它不起作用。它是一个外部文件。你可以解释如何让它像那样工作吗?还是我傻?
  • @amon - 这是一个很好的建议。最初以 __DATA__ 开头,但走这条路认为 OP 可以用文件名替换 $data 的值。
  • @Mombassa - 您可以这样做:my $data = 'ages.txt';,然后删除 open$data 之前的前导反斜杠:open my $fh, '&lt;', $data or die $!;
【解决方案2】:

您可以将文件读入数组引用数组,然后根据每个数组的第二个字段进行排序:

my @lines;
open (FILEHERE, 'ages.txt');
while(<FILEHERE>) {
    push @lines, [split /\t/];
}

my @sorted = sort { $b->[1] <=> $a->[1] } @lines;

或者,假设您的数据已正确排序,那么编写 Perl 脚本可能更容易,并且只需从标准输入读取:sort -grk2 ages.txt | perl yourscript.pl

【讨论】:

  • 结果:ARRAY(0x47973e0) ARRAY(0x4691990) ARRAY(0x47973b0) 内存引用?
  • 是的,每一行都存储为一个数组,@sorted 的内容是对这些数组的引用。要获取$a 引用的数组,请使用@{$a}
  • 尝试打印@sorted .. 它给了我上面的信息,所以我尝试打印@{$a} 并且我得到:不能使用未定义的值作为ARRAY 引用在.. . 第 406 行, 第 3 行。
  • 你需要遍历数组的值:试试print $_-&gt;[0], "\t", $_-&gt;[1] foreach @sorted。或更明确地说:foreach my $l (@sorted) { print $l-&gt;[0], "\t", $l-&gt;[1] }
  • 天哪,这样的简单已经连续 8 小时了。干杯
【解决方案3】:

How to sort an array or table by column in perl? 的这一个班轮应该可以工作:

perl -anE 'push @t,[@F]}{ say "@$_" for sort {$a->[1] <=> $b->[1]} @t' names.txt

与@reo katoa 一样,它使用数组数组-但首先利用-a 将行自动拆分为@F。有关自动拆分的详细信息,请参阅perlrun

【讨论】:

    【解决方案4】:

    您也可以在 perl 中调用 sort -k 2,2 对第二个字段的文件进行排序,当然如果它们是数字则使用 -n 并使用 -r 进行反向排序。

    我使用下面的单行来查看 squid 访问日志,它在顶部显示了最长的会话

    sort -rn -k 2,2 access.log | perl -lpe 's/^([0-9]{10})(.\d{3})/scalar localtime$1/e'
    

    【讨论】:

      猜你喜欢
      • 2013-03-09
      • 1970-01-01
      • 1970-01-01
      • 2017-11-13
      • 1970-01-01
      • 1970-01-01
      • 2021-05-11
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多