특정 문구가 파일에 나타나는 횟수를 계산하고 깔끔하게 서식을 지정하려면 어떻게 해야 합니까?

특정 문구가 파일에 나타나는 횟수를 계산하고 깔끔하게 서식을 지정하려면 어떻게 해야 합니까?

데이터를 추출하려는 로그 파일이 있습니다. 특정 모듈이 체크인 및 체크아웃될 때 다음과 같은 형식과 목록이 있습니다.

19:50:26 (license_manager) OUT: "certain_module" [email protected]
19:50:28 (license_manager) IN: "rarely_used_module" [email protected]
19:50:28 (license_manager) IN: "certain_module" [email protected]
19:50:28 (license_manager) IN: "different_module" [email protected]
19:50:38 (license_manager) OUT: "certain_module" [email protected]
19:50:38 (license_manager) OUT: "different_module" [email protected]

지금까지 나는 다음을 가지고 있습니다. 나는 "rarely_used_module"이 언제 확인되는지, 그리고 누가 확인하는지에 특히 관심이 있습니다.

cd /path/to/script && cat logfile.txt | grep -c "rarely_used_module" 

하지만 이것은 나에게 카운트만 제공하고 다른 것은 없습니다. 나는 두 가지 이유로 이를 더 복잡하게 만들고 싶습니다. 쉘 스크립트에 대해 더 자세히 배우고 해당 스크립트에 더 많은 bash 개념을 구현하기 위해, 두 번째로 라이선스가 체크아웃된 시기와 어떤 사용자가 조회했는지 알려줄 수 있기를 원합니다. 그것.

가장 이상적인 방법은 이 라이센스가 체크아웃된 횟수를 세어 참조용으로 일종의 표로 형식화하는 것입니다. 가능합니까?

업데이트 #1

원하는 출력은 아래와 같습니다. 아래에서는 거의 사용되지 않는 모듈이 2명의 고유 사용자에 의해 4번, 개별적으로 2번 체크아웃된 이론적인 예를 제시하겠습니다.

Number of license checkouts for rarely_used_module: 4 
User : [email protected] (2)
User : [email protected] (2)

기본적으로 모듈이 체크아웃된 총 횟수와 라이센스를 체크아웃한 사용자의 이름을 원합니다. "rarely_used_module"의 OUT: 행을 잡을 수 있다는 것을 알고 있지만 이를 처리하는 방법을 모르겠습니다.

답변1

업데이트된 질문의 경우:

awk '
/"rarely_used_module"/ && /OUT:/ { nc[$NF]++ ; c++ }
END {
    printf "Number of license checkouts for rarely_used_module: %d\n", c
    for (i in nc) printf "User: %s (%d)\n", i, nc[i]
}
' logfile.txt

다음 출력을 생성합니다.

Number of license checkouts for rarely_used_module: 4
User: [email protected] (2)
User: [email protected] (2)



요구 사항이 증가할 경우 코드를 확장하는 방법을 보여주기 위해 아래에 원래 답변을 남겨 두었습니다.

다음은 다음을 사용하여 이러한 작업을 수행하는 방법의 예입니다 awk.

awk '
BEGIN { SUBSEP = ", " ; OFS = ": " }
{ m[$(NF-1)]++ }
{ n[$(NF-1)] = n[$(NF-1)] " " $NF }
{ nc[$(NF-1),$NF]++ }
END {
    print "\n=== count modules:"
    for (i in m) print i, m[i]
    print "\n=== collect names using modules:"
    for (i in n) print i, n[i]
    print "\n=== count names using modules:"
    for (i in nc) print i, nc[i]
}
' logfile.txt

설명하다:

  • { m[$(NF-1)]++ }- 입력 데이터에서 두 번째 필드(모듈)의 카운터를 증가시킵니다.
  • { n[$(NF-1)] = n[$(NF-1)] " " $NF }- 각 키(모듈)의 마지막 필드(이름)를 연결합니다.
  • { nc[$(NF-1),$NF]++ }- (이름, 모듈) 키 튜플의 카운터 증가

예제 데이터를 사용하면 다음과 같은 출력이 생성됩니다.

=== count modules:
"rarely_used_module": 1
"different_module": 2
"certain_module": 3

=== collect names using modules:
"rarely_used_module":  [email protected]
"different_module":  [email protected] [email protected]
"certain_module":  [email protected] [email protected] [email protected]

=== count names using modules:
"different_module", [email protected]: 1
"different_module", [email protected]: 1
"certain_module", [email protected]: 2
"rarely_used_module", [email protected]: 1
"certain_module", [email protected]: 1

답변2

모든 줄을 변경하거나 일치시키는 것보다 더 복잡한 것이 필요할 때 Python은 범용 언어이기 때문에 사용합니다. awk(btw, Python awk가 있습니다 ) 보다 더 장황할 수도 있지만 pawk잘 문서화되어 있고 쉽게 확장할 수 있는 코드도 제공합니다.

다음은 작업에 적합한 Python 2 스크립트입니다.

from collections import defaultdict

FILE = 'module.txt'

# Global table of usages is 
# dict [ module_name ] -> dict [ user_name ] -> count
usage = defaultdict(lambda : defaultdict(int))

# Read, parse data and add usage count where needed
with open(FILE) as f:
    for line in f:
        # Split using spaces and pick last 2 fields, 
        # strip unncessary characters
        fields = line.split()     
        user = fields[-1].rstrip()
        module_name = fields[-2].strip('"')

        usage[module_name][user] += 1

# Now print pretty results
for module_name, module_usage in usage.items():
    print '====> ', module_name
    for user, count in module_usage.items():
        print '\t', user, count

샘플에 대해 다음 데이터가 인쇄됩니다.

====>  different_module                                                                                                                                                        
        [email protected] 1
        [email protected] 1
====>  rarely_used_module
        [email protected] 1
====>  certain_module
        [email protected] 2
        [email protected] 1

관련 정보