AWK를 사용하여 맵파일과 함께 로드된 파일을 쿼리하는 방법 [닫기]

AWK를 사용하여 맵파일과 함께 로드된 파일을 쿼리하는 방법 [닫기]

저는 두 로그 파일(In.log 및 Out.log) 간의 참조를 연관시키기 위해 Ubuntu에서 awk를 사용하고 있습니다. 예상대로 작동하지만 Out.log의 크기가 증가(~K라인)되어 처리 시간도 늘어납니다! 그래서 디스크 액세스를 줄이기 위해 MAPFILE 명령이나 이와 유사한 명령을 사용하여 루프 전에 이 Out.log 파일을 메모리에 한 번 로드할 수 있는지 궁금했지만 유용한 예를 본 적이 없습니다. 어떤 제안이 있으십니까?

입력 로그:

2016-10-20 19:20:00,IN,DEU00000000159560100
2016-10-22 19:22:20,IN,DEU00000000159560511
2016-10-24 19:24:20,IN,DEU00000000159560382
2016-10-26 19:26:20,IN,DEU00000000159560609
2016-10-28 19:28:20,IN,DEU00000000159560809

출력 로그:

2016-10-20 19:20:30,OUT,DEU00000000159560100
2016-10-21 19:21:30,OUT,DEU00000000159560510
2016-10-22 19:22:30,OUT,DEU00000000159560511
2016-10-23 19:23:30,OUT,DEU00000000159560381
2016-10-24 19:24:30,OUT,DEU00000000159560382
2016-10-25 19:25:30,OUT,DEU00000000159560195
2016-10-26 19:26:30,OUT,DEU00000000159560609
2016-10-27 19:27:30,OUT,DEU00000000159560433
2016-10-28 19:28:30,OUT,DEU00000000159560809
2016-10-29 19:29:30,OUT,DEU00000000159560694

현재 스크립트:

cat IN.LOG | while read -r Line
do
    Reference=$(cut -f3 -d',' <<< $Line)
    TimeStampIn=$(cut -f1 -d',' <<< $Line)
    TimeStampOut=$(awk -F',' -v Ref=$Reference '$3==Ref {print $1; exit} ' OUT.LOG)
    echo "$Reference,$TimeStampIn,$TimeStampOut"
done

답변1

다음과 같은 명령 만 있으면 됩니다 awk.

awk -v reflog=OUT.LOG '
    BEGIN{
      FS=OFS=",";
      while((getline <reflog) > 0) refs[$3]=$1;
      close(reflog)
    }{
      print $3,$1,refs[$3] ? refs[$3] : "not found"
    }' IN.LOG

또는 join다음과 같은 사용 사례를 위해 특별히 설계된 것을 사용하십시오.

join -t, -j 3 -o 0,1.1,2.1 -a 1 -e "not found" \
  <(sort -t, -k3 IN.LOG) <(sort -t, -k3 OUT.LOG) \
  | sort -t, -k2

join입력 파일은 "조인 열"을 기준으로 정렬되어야 합니다 . 이것이 바로 두 로그 파일을 먼저 참조 열을 기준으로 정렬한 다음 출력을 날짜별로 정렬하는 이유입니다.

두 솔루션은 다르게 동작합니다.OUT.LOG의 고유하지 않은 참조에 대해. awkOUT.LOG의 중복 참조는 무시되지만(마지막 참조가 우선) join모든 일치 항목이 인쇄됩니다. 또한 -a 2명령에 추가하면 join인쇄됩니다.모두페어링할 수 없는 회선입니다.

관련 정보