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

그러나 이 프로그램은 별로 유용하지 않습니다. 실제로는 네 가지 검색 기준 모두와 정확히 일치하는 행을 인쇄하는 한 가지 작업만 수행합니다.

참고: 일반적으로 이와 같은 프로그램의 경우 필터로 작성하는 것이 좋습니다. 즉, 특정 파일 이름을 프로그램에 하드코딩하는 대신 표준 입력 및/또는 명령줄에 언급된 파일 이름에서 입력을 가져옵니다.

이 방법을 사용하면 어떤 파일 이름에도 사용할 수 있고 다른 프로그램의 입력 grep이나 출력을 가져올 수도 있습니다.awk

Perl의 파일 핸들은 <>바로 이것을 수행합니다. 표준 입력에서 입력을 받습니다.그리고명령줄에 인수로 제공된 파일 이름입니다(있는 경우). while (<>) { ...code... }표준 입력 및/또는 파일 입력에 대한 검색, 형식 변경, 데이터 추출 및 기타 작업을 수행하는 Perl 프로그램에서 자주 볼 수 있습니다.


어제의 비슷한 질문에 따르면, 단지 arrays가 아닌 의미 있는 이름을 가진 변수를 원한다면 @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 -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

관련 정보