我有一个如下所示的日志文件:
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 none 而有些则没有。我想在散列中保留具有“R 集成”和“IDLE 无”的那些,而忽略其余的。我已经尝试了以下代码,但没有得到想要的结果。
#!/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。谢谢。
最佳答案
我对你的程序做了一些修改:
- 总是输入
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;
关于linux - Perl if 条件参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19145245/