Regex 在Perl中,如何将数组作为值存储在散列中?
我不知道你是否可以问关于学校作业的问题。我只是想知道我应该做什么,而不是为我做这件事。也许我错过了一些非常简单的东西,它就在我面前,但无论如何,它是基于一个较旧的作业,但我错过了这门课,我现在遇到了一堵墙,问题是我试图将数组推到哈希表中。使用类似这样的东西Regex 在Perl中,如何将数组作为值存储在散列中?,regex,perl,hashtable,Regex,Perl,Hashtable,我不知道你是否可以问关于学校作业的问题。我只是想知道我应该做什么,而不是为我做这件事。也许我错过了一些非常简单的东西,它就在我面前,但无论如何,它是基于一个较旧的作业,但我错过了这门课,我现在遇到了一堵墙,问题是我试图将数组推到哈希表中。使用类似这样的东西 push @{$hash_table{$hash_key}}, $port 以及在存储端口时对端口进行计数,然后打印哈希的内容 while ( ($key , $value) = each ( %hash ) ) { print “
push @{$hash_table{$hash_key}}, $port
以及在存储端口时对端口进行计数,然后打印哈希的内容
while ( ($key , $value) = each ( %hash ) ) {
print “$key scanned @{$value}”
}
如果我想对结果进行排序,我会使用
< foreach $key ( keys ( %hash ) ) {
}
我当前的代码是这样的,搜索/inxt-DROP字符串/
使用提供的日志文件。我不能为我的生活找到正确的地方添加上述代码
use warnings;
my $LogRecord;
my $LogRecordCount;
open LOGFILE, "sample.log.txt" or die "couldn't open sample.log.txt";
while ($LogRecord = <LOGFILE>) {
if ($LogRecord =~ /INext-DROP/) {
$LogRecordCount ++;
$LogRecord =~ /(SRC=[0-9\.]* ).*(SPT=[0-9\.]* )/;
$source=$1;
$sport=$2;
print "$source$sport";
print substr( $LogRecord , 0 , $ARGV[1] ) , "\n" if $ARGV[1];
}
}
print "The file contained $LogRecordCount records" if $ARGV[1];
close LOGFILE;
使用警告;
我的$LogRecord;
我的$LogRecordCount;
打开日志文件“sample.log.txt”或die“无法打开sample.log.txt”;
而($LogRecord=){
如果($LogRecord=~/inxt DROP/){
$LogRecordCount++;
$LogRecord=~/(SRC=[0-9\.]*)。*(SPT=[0-9\.]*)/;
$source=$1;
$sport=$2;
打印“$source$sport”;
打印substr($LogRecord,0,$ARGV[1]),“\n”如果$ARGV[1];
}
}
如果$ARGV[1],则打印“包含$LogRecordCount记录的文件”;
关闭日志文件;
这是一张带有注释的旧代码的图片;
您似乎遇到的问题是,您不确定端口被捕获的位置和哈希更新 发生的事情是,当
循环一次迭代一行文件时,将值捕获到$LogRecord=~
行正在捕获模式中,$1
和$2
然后,$2
就是你可以通过推送
添加到散列中的东西
然而,我在风格方面做了一些改变,比如使用词法文件句柄,因为这是更好的风格
#!/usr/bin/env perl
use warnings;
use strict;
#because it makes debugging easier.
use Data::Dumper;
my $LogRecordCount;
#declare some hashes;
my %ports_from;
my %ips_that_used;
open my $logfile, "sample.log.txt" or die "couldn't open sample.log.txt";
while (my $line = <$logfile>) {
#matches 'current line' - skips stuff that doesn't match.
next unless $line =~ /INext-DROP/;
#increment count.
$LogRecordCount++;
my ( $source, $src_port ) = $line =~ m/SRC=([0-9\.]+).*SPT=([0-9]+)/;
print "$source$sport";
#not sure what this is doing, so I have left it in.
print substr( $line , 0 , $ARGV[1] ) , "\n" if $ARGV[1];
push @{$ports_from{$source}}, $src_port;
push @{$ips_that_used{$src_port}}, $source;
}
print "The file contained $LogRecordCount records" if $ARGV[1];
close $logfile;
print Dumper \%ports_from;
print Dumper \%ips_that_used;
如果要对它们进行排序,则必须使用sort
进行排序
现在,sort
是一个非常聪明的函数,但默认情况下是按字母数字排序。那是。。。实际上,当涉及到IP地址或端口号时,并不是所有这些都很有用,因为您可能希望对它们进行数字排序。简单的答案是Sort::Naturally
和使用sensort
但是-sort
接受一个函数(默认为cmp
),该函数根据相对位置返回-1、0、1
因此,“按IP”排序可能如下所示:
sub by_ip {
my @a = split /\./, $a;
my @b = split /\./, $b;
foreach my $octet ( @a ) {
my $comparison = $octet <=> shift ( @b );
return $comparison if $comparison;
}
return 0;
}
如果IP到端口的映射存在重复项,那么最好还是使用散列而不是数组散列来计算端口频率
$count_ports_from{$source}{$src_port}++;
然后:
foreach my $ip ( sort by_ip keys %count_ports_from ) {
print "$ip: ";
foreach my $port_num ( sort { $count_ports_from{$a} <=> $count_ports_from{$b} }
keys %{ $count_ports_from{$ip} } )
{
print "\t $port_num : $count_ports_from{$ip}{$port_num}\n";
}
}
您似乎遇到的问题是,您不确定捕获端口的位置和哈希更新
发生的事情是,当循环一次迭代一行文件时,将值捕获到$LogRecord=~
行正在捕获模式中,$1
和$2
然后,$2
就是你可以通过推送
添加到散列中的东西
然而,我在风格方面做了一些改变,比如使用词法文件句柄,因为这是更好的风格
#!/usr/bin/env perl
use warnings;
use strict;
#because it makes debugging easier.
use Data::Dumper;
my $LogRecordCount;
#declare some hashes;
my %ports_from;
my %ips_that_used;
open my $logfile, "sample.log.txt" or die "couldn't open sample.log.txt";
while (my $line = <$logfile>) {
#matches 'current line' - skips stuff that doesn't match.
next unless $line =~ /INext-DROP/;
#increment count.
$LogRecordCount++;
my ( $source, $src_port ) = $line =~ m/SRC=([0-9\.]+).*SPT=([0-9]+)/;
print "$source$sport";
#not sure what this is doing, so I have left it in.
print substr( $line , 0 , $ARGV[1] ) , "\n" if $ARGV[1];
push @{$ports_from{$source}}, $src_port;
push @{$ips_that_used{$src_port}}, $source;
}
print "The file contained $LogRecordCount records" if $ARGV[1];
close $logfile;
print Dumper \%ports_from;
print Dumper \%ips_that_used;
如果要对它们进行排序,则必须使用sort
进行排序
现在,sort
是一个非常聪明的函数,但默认情况下是按字母数字排序。那是。。。实际上,当涉及到IP地址或端口号时,并不是所有这些都很有用,因为您可能希望对它们进行数字排序。简单的答案是Sort::Naturally
和使用sensort
但是-sort
接受一个函数(默认为cmp
),该函数根据相对位置返回-1、0、1
因此,“按IP”排序可能如下所示:
sub by_ip {
my @a = split /\./, $a;
my @b = split /\./, $b;
foreach my $octet ( @a ) {
my $comparison = $octet <=> shift ( @b );
return $comparison if $comparison;
}
return 0;
}
如果IP到端口的映射存在重复项,那么最好还是使用散列而不是数组散列来计算端口频率
$count_ports_from{$source}{$src_port}++;
然后:
foreach my $ip ( sort by_ip keys %count_ports_from ) {
print "$ip: ";
foreach my $port_num ( sort { $count_ports_from{$a} <=> $count_ports_from{$b} }
keys %{ $count_ports_from{$ip} } )
{
print "\t $port_num : $count_ports_from{$ip}{$port_num}\n";
}
}
你绝对可以问关于作业的问题——但同样的规则适用于“真实”问题。e、 我们不会为你做作业(家庭作业或其他)。我们将帮助您理解您的问题并修复您正在处理的代码。粘贴一段日志(这样我们就不必从屏幕截图重建)将有助于测试。您不必问问题,也不必得到完美的答案,只需删除所有内容。Stackoverflow不是这样工作的。FYI@Sobrique。堆栈溢出的目的是提供一个参考源。回答你的问题是一个有益的副作用。但重要的是保留问题和答案,这样它可以作为参考。是的,它可以让人们在下学期用谷歌搜索这项作业。但也许他们也有同样的问题。Stackoverflow不是免费的一对一辅导服务。提出问题并得到回答的行为创造了一点以前不存在的知识。Stackoverflow的目的是通过分享这些知识来驱动访问者访问站点。如果这些知识只打算传授给你,我们将作为私人导师为个别提问者提供服务。对于这项服务,你必须付费。你绝对可以询问任务——但同样的规则适用于“真实”问题。e、 我们不会为你做作业(家庭作业或其他)。我们将帮助您理解您的问题并修复您正在处理的代码。粘贴一段日志(这样我们就不必从屏幕截图重建)将有助于测试。您不必问问题,也不必得到完美的答案,只需删除所有内容。Stackoverflow不是这样工作的。FYI@Sobrique。堆栈溢出的目的是提供一个参考源。回答你的问题是一个有益的副作用。但重要的是要保持