다중 패턴 일치 및 단일 라인 인쇄

다중 패턴 일치 및 단일 라인 인쇄

로그 파일에서 두 패턴을 일치시켜야 하고 (두 패턴 모두에서) 일치하는 패턴의 다음 줄을 가져와야 하며 마지막으로 이 세 값을 한 줄에 인쇄해야 합니다.

예제 로그 파일:

2013/09/05 04:26:00          Processing Batch /fbc/dev/cebi/dod/9739867262
2013/09/05 04:26:02          Batch 9739867262 was successful
2013/09/05 04:26:02          Total Time          =  3.13 Secs
2013/09/05 04:26:02          Repository API Time =  2.96 Secs
2013/09/05 04:26:02          File System Io Time =  0.06 Secs
2013/09/05 04:26:02          Doc Validation Time =  0.03 Secs
2013/09/05 04:26:02      Ending @ Thu Sep 05 04:26:02 EDT 2013
2013/09/05 08:18:10      Starting @ Thu Sep 05 08:18:10 EDT 2013
2013/09/05 08:18:10      Starting @ Thu Sep 05 08:18:10 EDT 2013
2013/09/05 08:18:10          Processing Batch /fbc/dev/cebi/dod/9844867675
2013/09/05 08:18:10          Processing Batch /fbc/dev/cebi/dod/9886743777
2013/09/05 08:18:16          Batch 9844867675 was successful
2013/09/05 08:18:16          Total Time          =  6.00 Secs
2013/09/05 08:18:16          Repository API Time =  5.63 Secs
2013/09/05 08:18:16          File System Io Time =  0.05 Secs
2013/09/05 08:18:16          Doc Validation Time =  0.19 Secs
2013/09/05 08:18:16      Ending @ Thu Sep 05 08:18:16 EDT 2013
2013/09/05 08:18:18          Batch 9886743777 was successful
2013/09/05 08:18:18          Total Time          =  8.27 Secs
2013/09/05 08:18:18          Repository API Time =  8.52 Secs
2013/09/05 08:18:18          File System Io Time =  0.08 Secs
2013/09/05 08:18:18          Doc Validation Time =  0.47 Secs
2013/09/05 08:18:18      Ending @ Thu Sep 05 08:18:18 EDT 2013

cust_no.txt라는 파일에 숫자를 따로 넣어두었습니다.

9739867262
9844867675
9886743777

이 숫자를 입력으로 사용하여 로그 파일에서 다음 두 패턴을 일치시켜야 합니다.

  1. 프로세스 배치 /fbc/dev/cebi/dod/
  2. 일괄 성공

출력에는 다음이 필요합니다.

-> 첫 번째 패턴( ) 일치에서 i.e Processing Batch /fbc/dev/cebi/dod/<numbers in the cust_no.txt>두 번째 단어인 $2를 가져와야 합니다. -> 두 번째 패턴( ) 일치에서 i.e Batch <numbers in the cust_no.txt> was successful두 번째 단어인 $2를 가져와야 합니다. -> 두 번째 패턴 이후 일치 항목 이후 다음 줄의 6번째 단어($6)(즉, 로 시작하는 줄 Total Time) 를 가져와야 합니다.

원하는 출력:

9739867262,04:26:00,04:26:02,3.13 Secs
9844867675,08:18:10,08:18:16,6.00 Secs
9886743777,08:18:10,08:18:18,8.27 Secs

이것을 얻기 위해 다음을 시도했지만 작동하지 않는 것 같습니다.

awk -v cn=$cust_no '{{if ($0 ~ "Processing.*" cn) st=$2 && if ($0 ~ "Customer cn was successful" et=$2; getline; tt=$4} ; print st,et,tt}

답변1

이건 어때:

while read number;do
    start=$(grep "Processing Batch /fbc/dev/cebi/dod/$number" log_file\
            |head -n 1|awk '{print $2}')
    end=$(grep -A 1 "Batch $number was successful" log_file\
            |head -n 2|tail -n 1|awk -v OFS=',' '{print $2,$6}')
    echo "$number,$start,$end Secs"
done <cust_no.txt

답변2

Perl과 grep을 사용해도 괜찮다면 여기에 문제에 대한 해결책이 있습니다. 다음은 스크립트입니다 cmd.pl.

#!/usr/bin/env perl

use feature 'say';
#use Data::Dumper;

@file = `grep -f cust_no.txt -A 1 sample.log`;

my (%info, $secLineSeen, $time, $custno);

$secLineSeen = 0;
foreach my $line (@file) {
    if ($secLineSeen == 1) {
        #2013/09/05 08:18:18          Total Time          =  8.27 Secs
        (my $totTime) = ($line =~ m!\S+ \S+\s+Total Time\s+=\s+(\S+ Secs)!);
        $info{$custno}{totTime} = $totTime;
        $secLineSeen = 0;

    } elsif ($line =~ m/Processing Batch/) {
        #2013/09/05 08:18:10          Processing Batch /fbc/dev/cebi/dod/9844867675
    ($time, $custno) = ($line =~ m!\S+ (\S+)\s+Processing Batch.*/(\S+)!);
        $info{$custno}{onetwo} = $time;

  } elsif ($line =~ m/Batch.*successful/) {
        #2013/09/05 08:18:18          Batch 9886743777 was successful
        ($time, $custno) = ($line =~ m!\S+ (\S+)\s+Batch (\S+) was.*!);
        $info{$custno}{twotwo} = $time;
        $secLineSeen = 1;
    }
}

#print Dumper(\%info);

#9739867262,04:26:00,04:26:02,3.13 Secs
foreach my $key (sort keys %info) {
    say "$key,$info{$key}{onetwo},$info{$key}{twotwo},$info{$key}{totTime}";
}

$ ./cmd.pl 
9739867262,04:26:00,04:26:02,3.13 Secs
9844867675,08:18:10,08:18:16,6.00 Secs
9886743777,08:18:10,08:18:18,8.27 Secs

세부 사항

@file이 Perl 스크립트는 먼저 이 명령의 결과를 포함하는 배열을 만듭니다 .

$ grep -f cust_no.txt -A 1 sample.log

이 명령은 아래와 같이 로그 파일을 가져와 sample.log파일에서 고객 번호가 포함된 모든 줄을 선택합니다 .cust_no.txt

2013/09/05 04:26:00          Processing Batch /fbc/dev/cebi/dod/9739867262
2013/09/05 04:26:02          Batch 9739867262 was successful
2013/09/05 04:26:02          Total Time          =  3.13 Secs
--
2013/09/05 08:18:10          Processing Batch /fbc/dev/cebi/dod/9844867675
2013/09/05 08:18:10          Processing Batch /fbc/dev/cebi/dod/9886743777
2013/09/05 08:18:16          Batch 9844867675 was successful
2013/09/05 08:18:16          Total Time          =  6.00 Secs
--
2013/09/05 08:18:18          Batch 9886743777 was successful
2013/09/05 08:18:18          Total Time          =  8.27 Secs

grep명령은 언급할 가치가 있는 한 가지 특별한 작업을 수행합니다. 주로 -A 1일치 항목() 뒤에 추가 줄을 유지합니다. 이를 통해 "총 시간"이 포함된 행을 가져올 수 있습니다.

이 데이터가 추출되면 Perl 스크립트는 질문에 언급된 요구 사항에 따라 다차원 해시를 사용하여 이 출력의 주요 데이터 조각 결과를 저장합니다.

콘텐츠 처리가 완료되면 해시는 다음과 같습니다 @file.

$VAR1 = {
          '9739867262' => {
                            'twotwo' => '04:26:02',
                            'totTime' => '3.13 Secs',
                            'onetwo' => '04:26:00'
                          },
          '9886743777' => {
                            'twotwo' => '08:18:18',
                            'totTime' => '8.27 Secs',
                            'onetwo' => '08:18:10'
                          },
          '9844867675' => {
                            'twotwo' => '08:18:16',
                            'totTime' => '6.00 Secs',
                            'onetwo' => '08:18:10'
                          }
        };

마지막으로, 이 해시를 반복하고 질문에 지정된 형식으로 수집한 내용을 인쇄합니다.

답변3

나는 grep을 시도할 것이다:

grep -EA 1 'pattern1|pattern2' file.log

-E 옵션을 사용하여 정규식을 확장하고 -A 옵션을 사용하여 일치시킬 줄 수를 지정합니다. 이제 이것을 한 줄로 인쇄하기 위해 sed를 사용하는 매우 해킹적인 방법을 생각할 수 있습니다.

grep -EA 1 'pattern1|pattern2' file.log | grep -v ^-- | sed 'N ; s+\n+|+g'

sed에 명령 N(다음 줄 읽기)을 전달하면 한 번에 두 줄의 입력을 처리할 수 있습니다. 반면에 이 명령을 사용하면 s+\n+|+g처리 중인 두 줄 사이의 줄 바꿈 문자를 바꾸거나(선택한 구분 기호로) 제거(바꾸기가 비어 있는 경우)하고 두 번째 줄 끝에 새 줄만 남길 수 있습니다. .

grep -v ^--첫 번째 grep 인스턴스의 출력을 제거해야 했습니다 --(아래 예시 참조).

Line 1
Line 2
--
Line X
Line Y

관련 정보