我的文本文件符合以下格式:
1 4730 1031782 init
4 0 6 events
2190 450 0 top
21413 5928 1 sshd
22355 1970 2009 find
我需要将其读入perl的数据结构中,这将允许我根据任何这些列进行排序和打印。
从左到右,各列分别是process_id
,memory_size
,cpu_time
和program_name
。
如何读取具有类似格式的文本文件,使我可以对数据结构进行排序并根据排序进行打印?
到目前为止我的尝试:
my %tasks;
sub open_file{
if (open (my $input, "task_file" || die "$!\n")){
print "Success!\n";
while( my $line = <$input> ) {
chomp($line);
($process_id, $memory_size, $cpu_time, $program_name) = split( /\s/, $line, 4);
$tasks{$process_id} = $process_id;
$tasks{$memory_size} = $memory_size;
$tasks{$cpu_time} = $cpu_time;
$tasks{$program_name} = $program_name;
print "$tasks{$process_id} $tasks{$memory_size} $tasks{$cpu_time} $tasks{$program_name}\n";
}
这确实可以正确打印输出,但是我无法弄清楚如何按特定列(即process_id或任何其他列)对所得的%tasks
哈希进行排序,并在排序格式。
答案 0 :(得分:2)
您正在将值存储在等于值的键下。使用Data::Dumper检查结构:
use Data::Dumper;
# ...
print Dumper(\%tasks);
您可以使用每列的值作为内键将pids存储在哈希哈希中。
#!/usr/bin/perl
use strict;
use warnings;
use feature qw{ say };
my @COLUMNS = qw( memory cpu program );
my %sort_strings = ( program => sub { $a cmp $b } );
my (%process_details, %sort);
while (<DATA>) {
my ($process_id, $memory_size, $cpu_time, $program_name) = split;
$process_details{$process_id} = { memory => $memory_size,
cpu => $cpu_time,
program => $program_name };
undef $sort{memory}{$memory_size}{$process_id};
undef $sort{cpu}{$cpu_time}{$process_id};
undef $sort{program}{$program_name}{$process_id};
}
say 'By pid:';
say join ', ', $_, @{ $process_details{$_} }{@COLUMNS}
for sort { $a <=> $b } keys %process_details;
for my $column (@COLUMNS) {
say "\nBy $column:";
my $cmp = $sort_strings{$column} || sub { $a <=> $b };
for my $value (sort $cmp keys %{ $sort{$column} }
) {
my @pids = keys %{ $sort{$column}{$value} };
say join ', ', $_, @{ $process_details{$_} }{@COLUMNS}
for @pids;
}
}
__DATA__
1 4730 1031782 init
4 0 6 events
2190 450 0 top
21413 5928 1 sshd
22355 1970 2009 find
但是,如果数据不是很大,并且排序不是时间紧迫的话,那么按给定列对整个数组进行排序就容易编写和读取:
#!/usr/bin/perl
use strict;
use feature qw{ say };
use warnings;
use enum qw( PID MEMORY CPU PROGRAM );
my @COLUMN_NAMES = qw( pid memory cpu program );
my %sort_strings = ((PROGRAM) => 1);
my @tasks;
push @tasks, [ split ] while <DATA>;
for my $column_index (0 .. $#COLUMN_NAMES) {
say "\nBy $COLUMN_NAMES[$column_index]:";
my $sort = $sort_strings{$column_index}
? sub { $a->[$column_index] cmp $b->[$column_index] }
: sub { $a->[$column_index] <=> $b->[$column_index] };
say "@$_" for sort $sort @tasks;
}
__DATA__
...
您需要安装enum发行版。
答案 1 :(得分:1)
我不知道如何按特定列对所得的
%tasks
哈希进行排序
您无法对哈希进行排序。您需要将每个输入行转换为哈希(成功完成),然后将所有这些哈希存储在数组中。然后,您可以按排序的顺序打印数组的内容。
这似乎可以满足您的要求:
#!/usr/bin/perl
use strict;
use warnings;
use feature 'say';
my @cols = qw[process_id memory_size cpu_time program_name];
@ARGV or die "Usage: $0 [sort_order]\n";
my $sort = lc shift;
if (! grep { $_ eq $sort } @cols ) {
die "$sort is not a valid sort order.\n"
. "Valid sort orders are: ", join('/', @cols), "\n";
}
my @data;
while (<DATA>) {
chomp;
my %rec;
@rec{@cols} = split;
push @data, \%rec;
}
if ($sort eq $cols[-1]) {
# Do a string sort
for (sort { $a->{$sort} cmp $b->{$sort} } @data) {
say join ' ', @{$_}{@cols};
}
} else {
# Do a numeric sort
for (sort { $a->{$sort} <=> $b->{$sort} } @data) {
say join ' ', @{$_}{@cols};
}
}
__DATA__
1 4730 1031782 init
4 0 6 events
2190 450 0 top
21413 5928 1 sshd
22355 1970 2009 find
DATA
文件句柄来简化代码。您需要将其替换为一些代码才能从外部文件读取。答案 2 :(得分:0)
这决定了如何使用脚本接收的第一个参数进行排序。
#!/usr/bin/env perl
use strict;
use warnings;
use feature 'say';
open my $fh, '<', 'task_file';
my @tasks;
my %sort_by = (
process_id=>0,
memory_size=>1,
cpu_time=>2,
program_name=>3
);
my $sort_by = defined $sort_by{defined $ARGV[0]?$ARGV[0]:0} ? $sort_by{$ARGV[0]} : 0;
while (<$fh>) {
push @tasks, [split /\s+/, $_];
}
@tasks = sort {
if ($b->[$sort_by] =~ /^[0-9]+$/ ) {
$b->[$sort_by] <=> $a->[$sort_by];
} else {
$a->[$sort_by] cmp $b->[$sort_by];
}
} @tasks;
for (@tasks) {
say join ' ', @{$_};
}