동일한 파일에서 awk를 두 번 실행하는 방법

동일한 파일에서 awk를 두 번 실행하는 방법

user_id가 포함된 로그 파일과 컨테스트 결과가 포함된 다른 열이 있습니다. 제 생각에는:

  1. 모든 승리한 사용자의 user_id 찾기
  2. 이러한 user_id가 주어지면 해당 사용자에 대한 모든 로그 항목을 반환합니다.

예:

로그.csv

id,user_id,winner,page_id
1,user_1,win,1
2,user_1,,10
3,user_2,,1
4,user_2,,2
5,user_4,win,10
6,user_5,,2
7,user_5,win,3

이와 같은 로그 파일이 있으면 현재 이를 두 단계로 나눕니다.

1단계: "win"이라는 단어가 언급된 모든 줄을 반환합니다.

/win/ {
    FS=","

    # To make unique, store user_id's in array
    n[$2] = 0
}

# Print the unique array keys
END{
    for (x in n)
        print x
}

이는 다음을 생성합니다.

user_1
user_4
user_5

이 출력을 파일에 저장합니다.output.txt

그런 다음 해당 파일과 원본 로그 파일을 다른 awk 파일에 전달합니다.

NR == FNR{
    n[$1] = 0   # Set the user ID to the array
    next        # Go to the next file
}
{
    FS=","
    if($2 in n){
        print $0
    }
}

그러면 올바른 출력이 반환됩니다(각 user_id에 대한 모든 승리 행).

1,user_1,win,1
2,user_1,,10
5,user_4,win,10
6,user_5,,2
7,user_5,win,3

이를 수행하는 더 우아한 방법이 있습니까? 단일 awk 파일을 사용하시겠습니까?

답변1

너무 늦었지만 후손을 위해 다음과 같이 할 수 있다는 점을 알려드리고 싶습니다.

awk '
   {
       # do first pass stuff
   }
   
   END
   {
       while(getline < FILENAME)
       {    
           # do second pass stuff
       }
       close(FILENAME)
   }
' file

더 많은 패스를 수행하려면 close(FILENAME)첫 번째 while 루프 다음에 두 번째 루프를 수행할 수 있습니다.

답변2

두 개의 배열을 사용하겠습니다.

awk -F, '{a[$0]=$2;if($3=="win")b[$2]++}END{for(i in a){if(b[a[i]])print i}}'

답변3

이를 수행하는 더 우아한 방법이 있습니까?

물론이죠. 제목에서 말한 대로 동일한 파일에 대해 Awk를 두 번 실행하면 됩니다.

awk -F, '$3=="win"{won[$2]} FNR==NR{next} $2 in won' log.csv log.csv

답변4

내 채우기 방법은 당신이 가지고 있는 grep것보다 더 빠릅니다.awkGNU grep펄 확장당신은 시도 할 수 있습니다

fgrep -f <(grep -oP "[^,]*(?=,win)" log.csv) log.csv

그렇지 않으면 출력을 파이프 perl.ext해야 합니다.grepcut

fgrep -f <(grep win log.csv | cut -d, -f2) log.csv

또는 사용하십시오 sed(위보다 조금 빠른 것 같습니다 grep| cut)

fgrep -f <(sed -n '/win/s/^[^,]*,\([^,]*\).*/\1/p' log.csv) log.csv

관련 정보