Arrays #!/usr/bin/perl,如何将字符串中的关键字与数字匹配

Arrays #!/usr/bin/perl,如何将字符串中的关键字与数字匹配,arrays,regex,perl,Arrays,Regex,Perl,背景:我正在使用一个Perl脚本向abuseipdb.com提交滥用报告。 脚本只有一个默认类别(14端口扫描),但我想为滥用报告提交正确的类别。提交类别是由一个数字完成的。可以使用多个类别,并用逗号“,”分隔 类别清单: 脚本的来源:,大致向下滚动到“abuseipdb_report.pl”的一半 我修改了脚本来扫描日志文件中的关键字,如果找到了,给它一个正确的分类号。(缺点:这种方式只能使用1个类别编号。) 它正在工作,但还远远不够漂亮。所有这些if和elsif语句都需要大量的处理时间 以下

背景:我正在使用一个Perl脚本向abuseipdb.com提交滥用报告。 脚本只有一个默认类别(14端口扫描),但我想为滥用报告提交正确的类别。提交类别是由一个数字完成的。可以使用多个类别,并用逗号“,”分隔

类别清单:

脚本的来源:,大致向下滚动到“abuseipdb_report.pl”的一半

我修改了脚本来扫描日志文件中的关键字,如果找到了,给它一个正确的分类号。(缺点:这种方式只能使用1个类别编号。)

它正在工作,但还远远不够漂亮。所有这些if和elsif语句都需要大量的处理时间

以下是我编造的片段。(正在工作!)

我尝试过数组和foreach循环,但我是Perl的新手,无法让它工作。所以我只能使用if-elsif代码

现在你知道我要做什么了

是否有一种更智能、更快的方法,可能包括多个类别

$logs示例:

2020/08/07 06:25:11 [error] 16769#0: *40996 [client 174.xxx.xxx.185] ModSecurity: Access denied with code 406 (phase 2). Matched "Operator `Within' with parameter `.asa/ .asax/ .ascx/ .axd/ .backup/ .bak/ .bat/ .cdx/ .cer/ .cfg/ .cmd/ .com/ .config/ .conf/ .cs/ .csproj/ .csr/ .dat/ .db/ .dbf/ .dll/ .dos/ .htr/ .htw/ .ida/ .idc/ .idq/ .inc/ .ini/ .key/ .licx/ .ln (150 characters omitted)' against variable `TX:EXTENSION' (Value: `.bak/' ) [file "/etc/modsecurity.d/REQUEST-920-PROTOCOL-ENFORCEMENT.conf"] [line "1015"] [id "920440"] [rev ""] [msg "URL file extension is restricted by policy"] [data ".bak"] [severity "2"] [ver "OWASP_CRS/3.3.0"] [maturity "0"] [accuracy "0"] [tag "application-multi"] [tag "language-multi"] [tag "platform-multi"] [tag "attack-protocol"] [tag "paranoia-level/1"] [tag "OWASP_CRS"] [tag "capec/1000/210/272"] [tag "PCI/6.5.10"] [hostname "46.xxx.xxx.137"] [uri "/wp-config.php.bak"] [unique_id "159678151143.002383"] [ref "o13,4o14,3v5,17o35,5t:urlDecodeUni,t:lower
 case"], client: 174.xxx.xxx.185, server: <removed>, request: "GET /wp-config.php.bak HTTP/1.1", host: "<removed>", referrer: "http://<removed>/"

做这些事情的通常方法是将您正在寻找的所有代币组合在一起,形成一个可以匹配一次的单一替代。比如说

my %keys = (
    'DOS-PROTECTION', 4,
    'PROTOCOL-ENFORCEMENT', 15,
    # ....
);
my $pattern = join '|', map quotemeta, sort keys %keys;
$pattern = qr/($pattern)/;

while (<DATA>) {
    my $cat = 14;
    $cat = $keys{$1} if /$pattern/;
    print "[$cat]\n";
}

__DATA__
blah blah DOS-PROTECTION blah blah
blah blah PROTOCOL-ENFORCEMENT blah blah
blah blah
blah blah
my%密钥=(
“DOS-保护”,4,
“协议执行”,15,
# ....
);
my$pattern=join'|',map quotemeta,排序键%keys;
$pattern=qr/($pattern)/;
而(){
我的$cat=14;
$cat=$keys{$1}if/$pattern/;
打印“[$cat]\n”;
}
__资料__
诸如此类的保护诸如此类的
诸如此类的协议执行诸如此类的
废话
废话

执行这些操作的通常方法是将您正在寻找的所有代币组合在一起,形成一个可匹配一次的替代代币。比如说

my %keys = (
    'DOS-PROTECTION', 4,
    'PROTOCOL-ENFORCEMENT', 15,
    # ....
);
my $pattern = join '|', map quotemeta, sort keys %keys;
$pattern = qr/($pattern)/;

while (<DATA>) {
    my $cat = 14;
    $cat = $keys{$1} if /$pattern/;
    print "[$cat]\n";
}

__DATA__
blah blah DOS-PROTECTION blah blah
blah blah PROTOCOL-ENFORCEMENT blah blah
blah blah
blah blah
my%密钥=(
“DOS-保护”,4,
“协议执行”,15,
# ....
);
my$pattern=join'|',map quotemeta,排序键%keys;
$pattern=qr/($pattern)/;
而(){
我的$cat=14;
$cat=$keys{$1}if/$pattern/;
打印“[$cat]\n”;
}
__资料__
诸如此类的保护诸如此类的
诸如此类的协议执行诸如此类的
废话
废话

一个明显的改进是将类别存储在一个数组中。这样,您可以提交多个类别:

my @cats = (14);

my $logs = $ARGV[6];
if    ($logs =~ m/DOS-PROTECTION/)          { push @cats, 4;}
elsif ($logs =~ m/PROTOCOL-ENFORCEMENT/)    { push @cats, 15;}
# etc...

my $data = {
  ip => $ARGV[0],
  comment => $comment,
  categories => join ',', @cats,
};

我也会考虑一个数据驱动的方法,其中匹配的字符串与相关的类别一起存储在哈希中。

my %categories = (
  'DOS-PROTECTION'       =>  4,
  'PROTOCOL-ENFORCEMENT' => 15,
  # etc...
);
然后可以使用循环进行检查:

my @cats = (14);

my $logs = $ARGV[6];

for (keys %categories) {
  if ($logs =~ /$_/) {
    push @cats, $categories{$_};
  }
}

一个明显的改进是将类别存储在一个数组中。这样,您可以提交多个类别:

my @cats = (14);

my $logs = $ARGV[6];
if    ($logs =~ m/DOS-PROTECTION/)          { push @cats, 4;}
elsif ($logs =~ m/PROTOCOL-ENFORCEMENT/)    { push @cats, 15;}
# etc...

my $data = {
  ip => $ARGV[0],
  comment => $comment,
  categories => join ',', @cats,
};

我也会考虑一个数据驱动的方法,其中匹配的字符串与相关的类别一起存储在哈希中。

my %categories = (
  'DOS-PROTECTION'       =>  4,
  'PROTOCOL-ENFORCEMENT' => 15,
  # etc...
);
然后可以使用循环进行检查:

my @cats = (14);

my $logs = $ARGV[6];

for (keys %categories) {
  if ($logs =~ /$_/) {
    push @cats, $categories{$_};
  }
}

您能展示一下$logs中的示例吗?问题中添加了$logs示例。我不能在这里提交。字符太多。添加了第二个示例。能否显示$logs中的内容示例?问题中添加了$logs示例。我不能在这里提交。字符太多。添加了第二个示例。我已使您的代码正常工作!我采用了数据驱动的方法。坦克!是否有删除重复类别的选项?遗憾的是,接收方没有筛选出重复的类别。找到了一种删除重复类别的方法:``my%hash=map{$\=>1}@cats@cats=密钥%hash;```来源:@karel跳过数组,直接将分类作为散列的键存储在集合中更简单
$cats{$categories{$1}}=1
来存储和
键%cats
来获得唯一的类别。我已经让你的代码工作了!我采用了数据驱动的方法。坦克!是否有删除重复类别的选项?遗憾的是,接收方没有筛选出重复的类别。找到了一种删除重复类别的方法:``my%hash=map{$\=>1}@cats@cats=密钥%hash;```来源:@karel跳过数组,直接将分类作为散列的键存储在集合中更简单
$cats{$categories{$1}}=1
存储并
键%cats
获取唯一的类别。您的代码尚未成功。我需要用$logs替换吗?我的示例代码只是从文件末尾的日志行中读取的一个演示。重新放置while循环,以获得日志文件的行。如果行在$logs中,则将条件更改为。。。如果$logs=~/$pattern/。如果$logs包含多行代码,您将不得不做一些不同的事情。您的代码尚未获得任何成功。我需要用$logs替换吗?我的示例代码只是从文件末尾的日志行中读取的一个演示。重新放置while循环,以获得日志文件的行。如果行在$logs中,则将条件更改为。。。如果$logs=~/$pattern/。如果$logs包含多行代码,您将不得不做一些不同的事情。