配信に失敗した電子メールの電子メールサーバーレポートを格納するメールボックスファイルを解析しています。不正な電子メールアドレスを抽出したいので、ログファイルは次のようになります。
...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つのp
… N
は次の行を読み取り、それをパターンスペースに追加します。
これが最終的な要約バージョンです…
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-- )"