オプションとなる可能性のある部分を含むテキストのブロックのグレッピング


8

非常に大きなログファイル、たとえばA.logイベントを説明する複数のエントリがあります。ログファイルのイベントエントリで2つのことを実行したいと思います。

  1. そのような各エントリの出現回数をカウントします(これは必須の要件ではありませんが、持っていると便利です)。
  2. 実際のエントリを別のファイルに抽出し、後で調べます。

典型的なイベントエントリは次のようになり、その間に他のテキストがあります。以下の例では、2つのイベントエントリがあり、最初のエントリには2つのDataChangeEntry ペイロードが含まれ、2番目のイベントには1 つの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を使用してもそれほど遠くはありません。だから私は専門家の助言を求めています。

PS:

  1. 私の要件についてもっと明確にしましょう。上記のテキストのブロック全体を逐語的にキャプチャし、必要に応じて、発生したそのようなブロックのインスタンスの数をカウントします。インスタンス数をカウントするオプションは必須ですが、必須ではありません。
  2. 問題の解決策がawkを使用している場合、awkファイルを保存して再利用したいと思います。そのため、スクリプトを実行する手順についても説明してください。私は正規表現とgrepを知っていますが、sedやawkに慣れていません。

彼らはいつもから始まりData control raising eventますか?
LatinSuD 2014年

@LatinSuDはい、常にその文字列で始まります。
オタク2014年

これはawkの仕事で、「ステートマシン」変数を使用していると思いますが、これに役立つ情報を追加する必要があります。
Didi Kohen 2014年

@DavidKohen イベントエントリは、「データコントロール発生イベント」トークンで始まり、新しい行の「]]」で終わります。そのような各イベントインスタンスを見つけたいと思います。
オタク2014年

それらについてはどうですか?彼らの量を数えますか?それらをすべて印刷しますか?質問を編集し、予想されるサンプル出力を追加してください(できれば異なるサンプル入力を使用してください)。
Didi Kohen 14年

回答:


4

これでうまくいくと思います。イベントは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作業ディレクトリで呼び出されるファイルで確認できます。


イベントヘッダーとは別にイベントカウンターをインクリメントする必要があります(または以前に演算子を使用する必要があります)。これにより、ヘッダーとフッターに異なる数値が表示され、読みにくくなります。
Didi Kohen 2014年

@LatinSuD私はawkに詳しくありません。したがって、上記のプログラムを実行するために必要な部分を追加できれば、非常に役立ちます。私にとって、入力ファイルはA.logです。
オタク2014年

このスクリプトを使用するには、inputfile.txtをファイル名に置き換えるか、猫とパイプを削除し、ファイル名を単一引用符の後に置きます。
Didi Kohen 14年

@DavidKohenこのスクリプトを保存したいと思います。つまり、findEvents.awkと保存します。次のように実行できますawk -f findEvents.awk A.logか?
オタク2014年

できますが、そのファイルの単一引用符内の部分のみを保存する必要があります。
Didi Kohen 2014年

2

非常に簡単なアプローチは

awk '{print > NR".entry"}END{print NR" entries"}' RS="]]" file 

これにより、エントリごとに個別のファイルが作成され、見つかったエントリの数が標準出力に出力されます。

説明

  • NRの現在の行番号ですawk
  • RS="]]"レコード区切り文字(「行」を定義するもの)をに設定し]]ます。つまり、各エントリはによって1行として扱われawkます。
  • {print > NR".entry"}:現在の行(エントリ)をというファイルに出力します[LineNumber].entry。したがって、1.entry1 2.entry番目、2番目などが含まれます。
  • 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 
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.