선택 사항이 될 수 있는 부분이 포함된 텍스트 블록 찾기

선택 사항이 될 수 있는 부분이 포함된 텍스트 블록 찾기

다음을 설명하는 항목이 여러 개 있습니다.이벤트매우 큰 로그 파일에서A.로그. 나는 두 가지 일을 하고 싶다.이벤트로그 파일의 항목:

  1. 각 항목의 발생 횟수를 계산합니다.(필수 요구 사항은 아니지만 있으면 좋을 것입니다.)
  2. 실제 항목을 별도의 파일로 추출하고 나중에 연구하십시오.

일반적인 이벤트 항목은 다음과 같으며 항목 사이에 다른 텍스트가 있습니다. 따라서 아래 예에는 두 가지가 있습니다.이벤트첫 번째 항목에는 두 개의 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을 사용하면 멀리 가지 않습니다. 그래서 전문가의 조언을 구하고 있습니다.

추신:

  1. 내 요구 사항에 대해 좀 더 명확하게 설명하겠습니다. 위에 표시된 전체 텍스트 블록을 그대로 캡처하고 선택적으로 이러한 블록이 발생한 인스턴스 수를 계산하고 싶습니다. 인스턴스 수를 계산하는 옵션이 있으면 좋지만 필수 요구 사항은 아닙니다.
  2. 문제에 대한 해결책이 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 

관련 정보