以下のログを含む大容量ファイルがあります。約30,000件のそのような出来事が記録されました。RINGING
and CLOSE
(includes)で始まり、含まない行を抽出する必要があります30 30
。
要件は次のとおりです。
以下に示す2つのインスタンスのうち、インスタンス2を維持するだけです。インスタンス1を完全に削除する必要があります(ファイルの大部分を占めます)。
例1:
313782 Aug 19 18:37:04.925: <DATA> RINGING|254|01136097645|5950|$hostIp|$size |$data
313783 Aug 19 18:37:05.262: <DATA> TRAINING|254|01136097645|5950|$hostIp|$size |$data
313784 Aug 19 18:37:09.028: <DATA> OUT |254|01136097645|5950|$hostIp|2 bytes |30 93
313785 Aug 19 18:37:09.705: <DATA> IN |254|01136097645|5950|$hostIp|4 bytes |30 73 F9 F8
313786 Aug 19 18:37:18.532: <DATA> IN |254|01136097645|5950|$hostIp|336 bytes |30 10 60 00 06 00 00 6F 12 00 ...
313787 Aug 19 18:37:19.485: <DATA> OUT |254|01136097645|5950|$hostIp|133 bytes |30 30 60 00 00 00 06 6F 12 10 ...
313788 Aug 19 18:37:20.898: <DATA> TRAINING|254|01136097645|5950|$hostIp|$size |$data
313789 Aug 19 18:37:22.006: <DATA> CLOSE|254|01136097645|5950|$hostIp|$size |$data
例2:
(30 30の行は存在しません)
313782 Aug 19 18:37:04.925: <DATA> RINGING|254|01136097645|5950|$hostIp|$size |$data
313783 Aug 19 18:37:05.262: <DATA> TRAINING|254|01136097645|5950|$hostIp|$size |$data
313784 Aug 19 18:37:09.028: <DATA> OUT |254|01136097645|5950|$hostIp|2 bytes |30 93
313785 Aug 19 18:37:09.705: <DATA> IN |254|01136097645|5950|$hostIp|4 bytes |30 73 F9 F8
313786 Aug 19 18:37:18.532: <DATA> IN |254|01136097645|5950|$hostIp|336 bytes |30 10 60 00 06 00 00 6F 12 00 ...
313788 Aug 19 18:37:20.898: <DATA> TRAINING|254|01136097645|5950|$hostIp|$size |$data
313789 Aug 19 18:37:22.006: <DATA> CLOSE|254|01136097645|5950|$hostIp|$size |$data
答え1
ログファイル名があると仮定すると、サンプル出力を含むソリューションlogfile
は次のようになります。awk
$ awk '/RINGING/,/CLOSE/ {if (/30 30/){f=1}; a=a"\n"$0} f==0 && /CLOSE/ {print a} /CLOSE/{a="";f=0}' logfile
313782 Aug 19 18:37:04.925: <DATA> RINGING|254|01136097645|5950|$hostIp|$size |$data
313783 Aug 19 18:37:05.262: <DATA> TRAINING|254|01136097645|5950|$hostIp|$size |$data
313784 Aug 19 18:37:09.028: <DATA> OUT |254|01136097645|5950|$hostIp|2 bytes |30 93
313785 Aug 19 18:37:09.705: <DATA> IN |254|01136097645|5950|$hostIp|4 bytes |30 73 F9 F8
313786 Aug 19 18:37:18.532: <DATA> IN |254|01136097645|5950|$hostIp|336 bytes |30 10 60 00 06 00 00 6F 12 00
313788 Aug 19 18:37:20.898: <DATA> TRAINING|254|01136097645|5950|$hostIp|$size |$data
313789 Aug 19 18:37:22.006: <DATA> CLOSE|254|01136097645|5950|$hostIp|$size |$data
説明する
awk
各コマンドを順番に実行します。
/RINGING/,/CLOSE/ {if (/30 30/){f=1}; a=a"\n"$0}
式
/RINGING/,/CLOSE/
は範囲です。コマンドが行グループにのみ適用されることを指定します。グループは、テキストを含む行に会うと開始されますRINGING
。CLOSE
テキストを含む行に会うと、グループは終了します。これらのグループのすべての行に対して中括弧で囲まれたコマンドが実行されます。f
最初は、行にが含まれている場合はフラグを1に設定します30 30
。 2番目のコマンドは現在の行を変数に追加しますa
。f==0 && /CLOSE/ {print a}
ここで中括弧内のコマンドの前には、2つの条件が一緒に接続されています。最初の条件はフラグが
f
0(30 30
グループに見つかりません)であることを指定し、2番目の条件は行にtextが含まれていることを指定しますCLOSE
。両方の条件が満たされると、変数に格納されてa
いる行グループを印刷します。/CLOSE/{a="";f=0}
最後に、textを含む行では、
CLOSE
変数は空のa
文字列にリセットされ、フラグはf
0に設定されます。これが完了すると、コードは次の行セット(存在する場合)から開始する準備が整います。
答え2
たとえば、Perl互換正規表現(PCRE)を使用できます。
pcregrep -M '^.*?RINGING(?(?!30 30)(?s).)+?CLOSE.*?$' file
または
grep -zPo '^.*?RINGING(?(?!30 30)(?s).)+?CLOSE.*?$' file
または、GNU awkのより表現力のあるレコード区切り文字を使用してください。
gawk -vRS="CLOSE[^\n]*\n" -vORS= '!/30 30/ {print; print RT}' file