선택적 섹션이 포함된 텍스트 블록 찾기

선택적 섹션이 포함된 텍스트 블록 찾기

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

  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. 메시지는 표준 출력으로 전송됩니다.

이 파일을 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].entry1.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 

관련 정보