有条件地在文本文件中打印元素

时间:2019-06-07 14:43:56

标签: perl

我有以下格式的文本文件:

1 4730 1031782 init
4 0 6 events
2190 450 0 top
21413 5928 1 sshd
22355 1970 2009 find 

仅当第二列数据符合要求>= 2000时,我才想打印此文件的行-我该怎么做?

当前,我正在读取文件并像这样打印它:

sub read_file{
  my $data_failed = 1;
  my $file = 'task_file';
  if(open (my $file, "task_file" || die "$!\n")){
    my @COLUMNS = qw( memory cpu program );
    my %sort_strings = ( program => sub { $a cmp $b } );

    my (%process_details, %sort);

    while (<$file>) {
      $data_failed = 0;
      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};
    }

    if($option_a == 1){
    if (-z $file){print "No tasks found\n";}
    for my $column ($COLUMNS[2]) {
      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;
        }
      }
    }
  } else { print "No tasks found\n"}
}

if($option_a == 1)位只是从另一个分析命令行选项的函数中读取值。

3 个答案:

答案 0 :(得分:1)

使用grep可以轻松过滤列表:

#!/usr/bin/perl
use strict;
use feature qw{ say };
use warnings;

my @COLUMNS = qw( memory cpu program );

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

for my $value (sort { $a cmp $b } keys %{ $sort{program} }) {
    my @pids = grep $process_details{$_}{memory} > 2000,
               keys %{ $sort{program}{$value} };
    say join ' ', $_, @{ $process_details{$_} }{@COLUMNS}
        for @pids;
}

__DATA__
...

答案 1 :(得分:1)

my ($process_id, $memory_size, $cpu_time, $program_name) = split;

这时,您可以完成循环,也可以继续到下一行。只需添加以下行即可:

next if $memory_size < 2000;

在拆分之后,您将消除内存中所有不符合您要求的记录。

答案 2 :(得分:1)

可能是这样的:

#!/usr/bin/perl

use strict;
use warnings;

while (<DATA>) {
  print if (split)[1] > 2000;
}

__DATA__
1 4730 1031782 init
4 0 6 events
2190 450 0 top
21413 5928 1 sshd
22355 1970 2009 find

不带参数的split()在空白处拆分$_(这是我们想要的)。然后,我们可以使用列表切片查看其中的第二个元素,如果该值大于2000,则打印该行。