
다음을 설명하는 항목이 여러 개 있습니다.이벤트매우 큰 로그 파일에서A.로그. 나는 두 가지 일을 하고 싶다.이벤트로그 파일의 항목:
- 각 항목의 발생 횟수를 계산합니다.(필수 요구 사항은 아니지만 있으면 좋을 것입니다.)
- 실제 항목을 별도의 파일로 추출하고 나중에 연구하십시오.
일반적인 이벤트 항목은 다음과 같으며 항목 사이에 다른 텍스트가 있습니다. 따라서 아래 예에는 두 가지가 있습니다.이벤트첫 번째 항목에는 두 개의 DataChangeEntry
페이로드가 포함되어 있고 두 번째 항목에는 하나의 DataChangeEntry
페이로드가 포함되어 있습니다.
Data control raising event :DataControl@263c015d[[
#### DataChangeEvent #### on [DataControl name=PatternMatch_LegendTimeAxis, binding=.dynamicRegion1. beam_project_PatternMatch_dashboard_LegendTimeAxis_taskflow_LegendTimeAxis_beamDashboardLegendTimeAxisPageDef_beam_project_PatternMatch_dashboard_LegendTimeAxis_taskflow_LegendTimeAxis_beamDashboardLegendTimeAxis_xml_ps_taskflowid.dynamicRegion58. beam_project_PatternMatch_view_LegendTimeAxis_taskflow_LegendTimeAxis_beamVizLegendTimeAxisPageDef_beam_project_PatternMatch_view_LegendTimeAxis_taskflow_LegendTimeAxis_beamVizLegendTimeAxis_xml_ps_taskflowid.QueryIterator]
Filter/Collection Id : 0
Collection Level : 0
Sequence Id : 616
ViewSetId : PatternMatch.LegendTimeAxis_V1_0_SN49
==== DataChangeEntry (#1)
ChangeType : UPDATE
KeyPath : [2014-06-26 06:15:00.0, 0]
AttributeNames : [DATAOBJECT_CREATED, COUNTX, QueryName]
AttributeValues : [2014-06-26 06:15:00.0, 11, StrAvgCallWaitTimeGreaterThanThreshold]
AttributeTypes : [java.sql.Timestamp, java.lang.Integer, java.lang.String, ]
==== DataChangeEntry (#2)
ChangeType : UPDATE
KeyPath : [2014-06-26 06:15:00.0, 0]
AttributeNames : [DATAOBJECT_CREATED, COUNTX, QueryName]
AttributeValues : [2014-06-26 06:15:00.0, 9, AverageCallWaitingTimeGreateThanThreshold]
AttributeTypes : [java.sql.Timestamp, java.lang.Integer, java.lang.String, ]
]]
someother non useful text
spanning multiple lines
Data control raising event :DataControl@263c015d[[
#### DataChangeEvent #### on [DataControl name=PatternMatch_LegendTimeAxis, binding=.dynamicRegion1. beam_project_PatternMatch_dashboard_LegendTimeAxis_taskflow_LegendTimeAxis_beamDashboardLegendTimeAxisPageDef_beam_project_PatternMatch_dashboard_LegendTimeAxis_taskflow_LegendTimeAxis_beamDashboardLegendTimeAxis_xml_ps_taskflowid.dynamicRegion58. beam_project_PatternMatch_view_LegendTimeAxis_taskflow_LegendTimeAxis_beamVizLegendTimeAxisPageDef_beam_project_PatternMatch_view_LegendTimeAxis_taskflow_LegendTimeAxis_beamVizLegendTimeAxis_xml_ps_taskflowid.QueryIterator]
Filter/Collection Id : 0
Collection Level : 0
Sequence Id : 616
ViewSetId : PatternMatch.LegendTimeAxis_V1_0_SN49
==== DataChangeEntry (#1)
ChangeType : UPDATE
KeyPath : [2014-06-26 06:15:00.0, 0]
AttributeNames : [DATAOBJECT_CREATED, COUNTX, QueryName]
AttributeValues : [2014-06-26 06:15:00.0, 11, StrAvgCallWaitTimeGreaterThanThreshold]
AttributeTypes : [java.sql.Timestamp, java.lang.Integer, java.lang.String, ]
]]
==== DataChangeEntry
이벤트 항목의 줄 수는 가변적일 수 있습니다. 또한 빈 이벤트 페이로드를 나타내는 오류 조건이 완전히 없을 수도 있으며 이 경우도 확실히 포착하고 싶습니다.
이 경우 항목의 출력이 여러 줄에 걸쳐 있기 때문에 일반 바닐라 grep을 사용하면 멀리 가지 않습니다. 그래서 전문가의 조언을 구하고 있습니다.
추신:
- 내 요구 사항에 대해 좀 더 명확하게 설명하겠습니다. 위에 표시된 전체 텍스트 블록을 그대로 캡처하고 선택적으로 이러한 블록이 발생한 인스턴스 수를 계산하고 싶습니다. 인스턴스 수를 계산하는 옵션이 있으면 좋지만 필수 요구 사항은 아닙니다.
- 문제에 대한 해결책이 awk를 사용하는 것이라면 awk 파일을 저장하고 다시 사용하고 싶습니다. 따라서 스크립트를 실행하는 단계도 언급해 주세요. 나는 regex와 grep을 알고 있지만 sed 및/또는 awk에는 익숙하지 않습니다.
답변1
이것이면 좋겠다. 이벤트는 파일로 이동합니다 events
. 그리고 메시지는 stdout으로 이동합니다.
이 파일을 myprogram.awk에 저장합니다(예:).
#!/usr/bin/awk -f
BEGIN {
s=0; ### state. Active when parsing inside an event
nevent=0; ### Current event number
printf "" > "events"
}
# Start of event
/^ *Data control raising event/ {
s=1;
dentries=0;
print "*** Event number: " nevent >> "events"
nevent++
}
# Standard event line
s==1 {
print >> "events"
}
# DataChangeEntry line
/^ *==== DataChangeEntry/ {
dentries ++
}
# End of event
s==1 && /^ *\]\]/ {
s=0;
print "" >> "events"
if(dentries==0){
print "Warning: Event " nevent " has no Data Entries"
}
}
END {
print "Total event count: " nevent
}
다양한 방법으로 호출할 수 있습니다.
myprogram.awk inputfile.txt
awk -f myprogram.awk inputfile.txt
샘플 출력:
Warning: Event 3 has no Data Entries
Total event count: 3
events
작업 디렉토리에 호출된 파일에서 모든 이벤트를 함께 확인할 수 있습니다 .
답변2
매우 간단한 접근 방식은 다음과 같습니다.
awk '{print > NR".entry"}END{print NR" entries"}' RS="]]" file
그러면 각 항목에 대해 별도의 파일이 생성되고 발견된 항목 수가 표준 출력으로 인쇄됩니다.
설명
NR
의 현재 줄 번호입니다awk
.RS="]]"
레코드 구분 기호("줄"을 정의하는 것)를 로 설정합니다]]
. 즉, 각 항목은 에서 한 줄로 처리됩니다awk
.{print > NR".entry"}
: 현재 행(항목)을 이라는 파일에 인쇄합니다[LineNumber].entry
. 따라서1.entry
첫 번째,2.entry
두 번째 등이 포함됩니다.END{print NR" entries"}
: 전체 입력 파일이 처리된 후 END 블록이 실행됩니다. 따라서 해당 시점에서NR
처리되는 항목 수가 됩니다.
이것을 별칭으로 저장하거나 다음과 같이 스크립트로 만들 수 있습니다.
#!/usr/bin/env bash
awk '{print > NR".entry"}END{print NR" entries"}' RS="]]" "$1"
foo.sh
그런 다음 대상 파일을 인수로 사용하여 스크립트를 실행합니다(이 스크립트가 호출되고 $PATH에 있다고 가정 ).
foo.sh file
출력 파일 이름을 조정할 수도 있습니다. 예를 들어 파일을 호출하려면 [date].[entry number].[entry]
다음을 대신 사용하세요.
#!/usr/bin/env bash
date=$(date +%Y%m%d)
awk '{print > d"."NR".entry"}END{print NR" entries"}' RS="]]" d="$date" "$1"
위의 내용에서는 로그 파일이 "이벤트" 항목으로만 구성되어 있다고 가정합니다. 그렇지 않고 다른 줄이 있을 수 있고 해당 줄을 무시해야 하는 경우 대신 다음을 사용하십시오.
#!/usr/bin/env bash
date=$(date +%Y%m%d)
awk '{
if(/\[\[/){a=1; c++;}
if(/\]\]/){a=0; print > d"."c".entry"}
if(a==1){print >> d"."c".entry"}
}' d="$date" file
또는 한 줄로 다음과 같이 하십시오.
awk '{if(/\[\[/){a=1; c++;}if(/\]\]/){a=0; print > d"."c".entry"}if(a==1){print >> d"."c".entry"}}' d=$(date +%Y%m%d) file