配信に失敗した電子メールの電子メールサーバーレポートを格納するメールボックスファイルを解析しています。不正な電子メールアドレスを抽出したいので、ログファイルは次のようになります。

...some content... The mail system <[email protected]>: host mx1.hotmail.com[65.54.188.94] said: 550 Requested action not taken: mailbox unavailable (in reply to RCPT TO command) ...some content... The mail system <[email protected]>: host viking.optimumpro.net[79.101.51.82] said: 550 Unknown user (in reply to RCPT TO command) ...some content... The mail system <[email protected]>: host mta5.am0.yahoodns.net[74.6.140.64] said: 554 delivery error: dd This user doesn"t have a yahoo.com account ([email protected]) [0] - mta1172.mail.sk1.yahoo.com (in reply to end of DATA command) ...etc. 

電子メールアドレスは「Themailsystem」の行の2行後に続きます。 。このようにgrepを使用すると、「メールシステム」行と次の2行が表示されます。

grep -A 2 "The mail system" mbox_file 

ただし、削除する方法がわかりません。 「メールシステム」行とこの出力からの2番目の空の行。 PHP / Perl / Pythonスクリプトを書いてそれを行うことができると思いますが、これはgrepやその他の標準ツールで可能かどうか疑問に思います。 -Bパラメータに負のオフセットを与えようとしました:

grep -A 2 -B -2 "The mail system" mbox_file 

しかしgrepが文句を言います:

grep: -2: invalid context length argument 

grepでこれを行う方法はありますか?

コメント

  • -Bは-Aと同じように数字を受け入れ、試合前の前の行。
  • はい、その通りですが、ミランは試合の前の行に関心がありません'。 。彼が遭遇した問題は、-Aと-Bは正の値のみを受け入れることです…そして、いずれの場合でも、-Aと-Bは相互に関連して使用できないことです' 、彼がやろうとしたように。
  • 念のために言っておきますが、これらは、与えられたファイルから(直接)抽出しなかったダミーアドレスですよね?
  • @Matthieu M.いいえ、実際のログファイルからのものです。とにかく無効なアドレスなので、'有効なダミーアドレスを発明するポイントは何だと思いました。
  • stackoverflow.com/questions/8101701/ …

回答

grepのみを使用して解決する最も簡単な方法は、最後にもう1つ反転したgrepをパイプすることです。 。例:

grep -A 4 "The mail system" temp.txt | grep -v "The mail system" | grep -v "^\d*$" 

回答

ロックインされていない場合grepを使用して、sed

sed -n "/The mail system/{n;n;p}" 

を試してください。 「Themailsystem」を含む行を見つけ、n;n;を介して次の行を2回読み取り、前の各行を破棄します。
これで3行目が残ります。グループのパターンスペースで、sed “s pコマンドを使用して印刷されます。先頭の-nオプションは、他のすべての印刷を防ぎます。 。

次の2行も印刷するには、 nextとprint n;pをさらに2回実行します。

sed -n "/The mail system/{n; n;p; n;p; n;p}" 

必要な行の次の行の読み取りは、1つのpNは次の行を読み取り、それをパターンスペースに追加します。

これが最終的な要約バージョンです…

sed -n "/The mail system/{n;n;N;N;p}" 

grep wouuldの出力と同様に、グループセパレーターが必要な場合は、sed “s insert コマンドを使用できます。 i(これは行の最後のコマンドである必要があります)…

これはグループセパレーターを含めるための構文です

sed -n "/The mail system/{n;n;N;N;p;i-- }" > output-file # or | ... 

最初の一致の出力は次のとおりです。

<[email protected]>: host mx1.hotmail.com[65.54.188.94] said: 550 Requested action not taken: mailbox unavailable (in reply to RCPT TO command) -- 

コメント

  • +1。ありがとうございます。この場合は'必要ありませんが、'より複雑な処理が必要になった場合に備えて、このブックマークを付けておきます。
  • これはすばらしい答えです!

回答

grep -A 2 -B -2 "The mail system" mbox_file 

-Bは前の行用であるため、負の値を指定する必要はありません。

grep -A 2 -B 2 "The mail system" mbox_file # This will work please check 

コメント

  • これは質問に答えません。 -A 2 -B 2は、コンテキストの前の2行からコンテキストの後の2行に出力します。問題は、コンテキストの後の2行からコンテキストの後の4行への印刷に関するものです。

回答

I 「厳密な制約。grepへの1回の呼び出しでは実行できない」場合を除いて、grepのみを使用しても意味がありません。

grep -A 2 "The mail system" mbox_file | tail -n +3 
  • grep:行を見つけて、2行後に出力します。
  • tail:最初の2行を切り取ります(つまり、3行目から開始します)。

コメント

  • これは、一致する行が1つしかない場合にのみ機能します。これは、おそらく質問が求めているものではありません。
  • それは、質問が求めているものではありませんが、私の現在の状況で私を助けてくれます:-)。
  • @ daniel.neumann私は知っていますが、私はまさにあなたの立場にあり、他の人のことを考えていました' Google-fu willここもリードします。

回答

最初の2行を削除する場合は、

sed "1,2d" 

のように

 grep -A 2 "The mail system" mbox_file | sed "1,2d"  

コメント

  • パターンが何度も発生するという事実を見逃しました。 「メールシステム」が4、14、24、34、…の行に表示されている場合、OPは6、16、26、36、…の行を見たいと考えています。 36、…。

回答

これは、Perlを使用して、正規表現の一致に続く次の1行を出力します

perl -ne "print if( (/The mail system/ && ($end=1))..!$end-- )" 

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です