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