我有一个如下所示的日志文件:
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。谢谢。
答案 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 integration
和IDLE none
的顺序始终如示例所示,则无需执行多个正则表达式匹配。当没有匹配时,您需要使用next
,因此您不会处理不匹配的行。
我怀疑你只想将哈希条目的值设置为字符串,而不是对另一个哈希的引用。