Perl if条件参数

时间:2013-10-02 19:27:56

标签: linux perl if-statement hash

我有一个如下所示的日志文件:

4680 p4exp/v68     PJIANG-015394 25:34:19 IDLE none
8869 unnamed p4-python       R integration semiconductor-project-trunktip-turbolinuxclient 01:33:52 IDLE none
8870 unnamed p4-python       R integration remote-trunktip-osxclient 01:33:52 

在同一个日志文件中有许多这样的条目,有些条目在末尾包含IDLE,而有些则不包含。我想保留散列中具有“R integration”和“IDLE none”的那些并忽略其余部分。我尝试了以下代码,但未获得所需的结果。

#!/usr/bin/perl
open (FH,'/root/log.txt');
my %stat;
my ($killid, $killid_details);
while ($line = <FH>) {
    if ($line =~ m/(\d+)/){
            $killid = $1;
    }
    if ($line =~ /R integration/ and $line =~ /IDLE none/){
            $killid_details = $line;
    }
    $stat{$killid} = {
            killid => $killid_details
    };
}
close (FH);

我得到R集成的所有行(例如我得到8869,8870行),不应该这样,因为8870应该被忽略。

如有任何错误,请通知我。我还在学习perl。谢谢。

2 个答案:

答案 0 :(得分:5)

我在您的计划中做了一些更改:

  • 始终加入use strict;use warnings;。这些将捕获90%的错误。 (虽然不是这次)。
  • 当您打开文件时,您需要使用or die中的open my $fh, "<", $file or die qq(blah, blah, blah);或使用use autodie;(现在首选)。在您的情况下,如果文件没有打开,您的程序将继续愉快地继续。您需要测试open语句是否有效。
  • 请注意我的open声明。我使用变量作为文件句柄。这是首选,因为它不是全局的,并且更容易传递到子例程。另请注意,我使用了三个参数open。这样,如果您的文件名以某些奇怪的字符开头,则不会遇到麻烦。
  • 当您声明变量时,最好在范围中执行。这样,当您不再需要变量时,变量将超出范围。我移动了$killid$killid_details在循环内声明的位置。这样,它们就不再存在于循环之外。
  • 你需要更加小心你的正则表达式。如果短语IDLE none出现在您的其他位置,该怎么办?如果它在行尾,你只需要它。

现在,针对您遇到的问题:

  • 阅读时需要chomp行。在Perl中,读入行尾的NL。chomp命令将其删除。
  • 你的逻辑有点奇怪。如果您的行中有一个数字,则设置$killid(我将其修改为仅查找行开头的数字)。但是,即使未设置killid,您也只是以快乐的方式继续前进。在您的版本中,因为您在循环之外声明了$killid,所以它在每个循环中都有一个值。如果未定义$killid,我将转到下一个语句。
  • 你的哈希有一个奇怪的定义。您正在哈希中定义引用哈希。没必要。我做了一个简单的哈希。

这是:

#! /usr/bin/env perl
use strict;
use warnings;
use feature qw(say);
use autodie;
use Data::Dumper;

open my $log_fh, '<', '/root/log.txt';

my %stat;
while (my $line = <$log_fh>) {
    chomp $line;
    next if not $line =~ /^(\d+)\s+/;
    my $killid = $1;
    if ($line =~ /R\s+integration/ and $line =~ /IDLE\s+none$/){
        my $killid_details = $line;
        $stat{$killid} = $killid_details;
    }
}
close $log_fh;

say Dumper \%stat;

答案 1 :(得分:1)

我认为这可能是你想要的:

while (<FH>) {
    next unless /^(\d+).*R integration.*IDLE none/;
    $stat{$1} = $_;
}

正则表达式应该固定在行的开头,因此您不能匹配行上任何位置的数字。假设R integrationIDLE none的顺序始终如示例所示,则无需执行多个正则表达式匹配。当没有匹配时,您需要使用next,因此您不会处理不匹配的行。

我怀疑你只想将哈希条目的值设置为字符串,而不是对另一个哈希的引用。