如何根据perl中的多个字段提取行

如何根据perl中的多个字段提取行

如何根据perl中的多个字段提取行

我有以下文件:file1.txt,我想根据多个字段的复合匹配提取行,这意味着如果该行仅包含所有这些字段的组合,则它应该提取包含这些字段的行

tcp
10.11.38.224
10.185.34.240
9012

文件1.txt

access firewall udp 10.14.90.111 240.230.111.222 10.13.45.21 255.255.230.240 eq 8443
access firewall tcp 10.11.38.224 255.233.212.111 10.185.34.240 244.255.240.211 eq 9012
#!/usr/bin/perl

open(SOURCE,"<file1.txt");
while (my @gitLines_mst = <SOURCE>)
{
my $fld0 = "tcp";
my $sIP = "10.11.38.224";
my $dIP = "10.185.34.240";
my $fld5 = "9012";
print "$fld0";
my @llll = grep {"/$fld0/" && "/$sIP/" && "/$dIP/" && "/$fld5"} @gitLines_mst;
print "here please: @llll \n";
}

我编写了上面的脚本,它再次列出了匹配的行以及文件的全部内容

我的输出:

access firewall udp 10.14.90.111 240.230.111.222 10.13.45.21 255.255.230.240 eq 8443
access firewall tcp 10.11.38.224 255.233.212.111 10.185.34.240 244.255.240.211 eq 9012

我什至在搜索时删除了双引号并尝试:

my @llll = grep {/$fld0/ && /$sIP/ && /$dIP/ && /$fld5} @gitLines_mst;

我收到错误:

Search pattern not terminated at ./sample line 11.

我想要的输出是:

access firewall tcp 10.11.38.224 255.233.212.111 10.185.34.240 244.255.240.211 eq 9012

答案1

#!/usr/bin/perl

while(<>) {
  @F = split;  # split input line into array @F using whitespace as separator.
  # Note: perl arrays start from 0, not 1.

  print if (($F[2] eq 'tcp') && 
            ($F[3] eq '10.11.38.224') &&
            ($F[5] eq '10.185.34.240') &&
            ($F[8] == 9012))
}

(该if语句可以全部写在一行上,但这样的格式更容易阅读)

将其保存到例如myscript.pl,使用 使其可执行chmod +x myscript.pl,并运行为:

$ ./myscript.pl file1.txt 
access firewall tcp 10.11.38.224 255.233.212.111 10.185.34.240 244.255.240.211 eq 9012

不过,这个程序并不是很有用。它实际上只做一件事,打印与所有四个搜索条件完全匹配的行。

注意:作为一般规则,对于这样的程序,最好将它们编写为过滤器 - 即从标准输入和/或命令行上提到的任何文件名获取输入,而不是将特定文件名硬编码到程序中。

这样,它可以与任何文件名一起使用,或者从grepawk或某些其他程序的输出获取输入。

Perl 中的文件<>句柄正是这样做的。它将从标准输入获取输入在命令行上作为参数给出的文件名(如果有)。 while (<>) { ...code... }您会在 Perl 程序中经常看到它,这些程序对标准输入和/或文件输入进行搜索、重新格式化、提取数据以及执行其他操作。


根据昨天的类似问题,如果您想要具有有意义名称的变量而不仅仅是数组@F,您可以这样写:

#!/usr/bin/perl

while(<>) {
  my ($access, $something, $proto, $srcIP, $srcmask,
      $destIP, $destmask, $eq, $port) = split;

  print if (($proto  eq 'tcp') && 
            ($srcIP  eq '10.11.38.224') &&
            ($destIP eq '10.185.34.240') &&
            ($port   == 9012))
}

您可以将其用于undef您不关心且不打算使用的任何字段。例如

  my (undef, undef, $proto, $srcIP, undef, $destIP, undef, undef, $port) = split;

顺便说一句,这样的事情也可以很容易地完成awk

$ awk '$3=="tcp" && $4=="10.11.38.224" && $6=="10.185.34.240" && $9==9012' file1.txt 
access firewall 1 10.11.38.224 255.233.212.111 1 244.255.240.211 eq 9012

或作为 perl 一行:

$ perl -lane 'print if $F[2] eq "tcp" && $F[3] eq "10.11.38.224" && $F[5] eq "10.185.34.240" && $F[8] == 9012' file1.txt 
access firewall tcp 10.11.38.224 255.233.212.111 10.185.34.240 244.255.240.211 eq 9012

相关内容