Ich analysiere eine Postfachdatei, in der E-Mail-Serverberichte für nicht erfolgreich zugestellte E-Mails gespeichert sind. Ich möchte ungültige E-Mail-Adressen extrahieren, damit ich sie aus dem System entferne. Die Protokolldatei sieht folgendermaßen aus:
...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.
E-Mail-Adresse kommt 2 Zeilen nach einer Zeile mit "Das Mail-System". Wenn ich grep so benutze, bekomme ich die Zeile "Das Mail-System" und die nächsten beiden Zeilen:
grep -A 2 "The mail system" mbox_file
Ich weiß jedoch nicht, wie ich die Zeile "Das Mailsystem" und die zweite leere Zeile aus dieser Ausgabe entfernen soll. Ich denke, ich könnte PHP / Perl / Python-Skript schreiben, aber ich frage mich, ob dies mit grep oder einem anderen Standard-Tool möglich ist. Ich habe versucht, dem Parameter -B einen negativen Offset zuzuweisen:
grep -A 2 -B -2 "The mail system" mbox_file
Aber grep beschwert sich:
grep: -2: invalid context length argument
Gibt es eine Möglichkeit, dies mit grep zu tun?
Antworten:
Der einfachste Weg, es
grep
nur mit Hilfe von zu lösen , besteht darin,grep
am Ende ein weiteres Rohr umzukehren . Zum Beispiel:quelle
Wenn Sie nicht an die Verwendung
grep
gebunden sind, versuchen Siesed
...Wenn es eine Zeile findet, die "Das Mail-System" enthält, liest es die nächste Zeile zweimal über
n;n;
, wobei jede vorherige Zeile dabei verworfen wird.Dadurch verbleibt die 3. Zeile Ihrer Gruppe im Musterbereich, der dann über den
p
Befehl sed gedruckt wird . Die führende-n
Option verhindert alle anderen Druckvorgänge.Um auch die nächsten beiden Zeilen zu drucken, müssen Sie nur next und noch
n;p
zweimal drucken .Die nächste Zeile liest für die Zeilen , die Sie benötigen , können mit nur einem einzigen Block aa gesammelt und gedruckt werden
p
...N
liest die nächste Zeile und fügt es dem Musterraum,Hier ist die endgültige Kurzfassung ...
Wenn Sie einen Gruppentrenner möchten , ähnlich wie bei der Ausgabe von grep wouuld, können Sie den Befehl insert von sed verwenden
i
(der der letzte Befehl in einer Zeile sein muss) ...Hier ist die Syntax, um einen Gruppentrenner einzuschließen
Hier ist die Ausgabe für das erste Match:
quelle
-B
gilt für vorherige Zeilen, daher muss -negative value nicht angegeben werden.quelle
-A 2 -B 2
druckt von zwei Zeilen vor dem Kontext bis zu zwei Zeilen nach dem Kontext. Die Frage betrifft das Drucken von 2 Zeilen nach dem Kontext bis 4 Zeilen nach dem Kontext.Ich sehe keinen Grund darin, nur grep (s) zu verwenden, außer wenn dies eine strenge Einschränkung ist. Es kann nicht mit einem Aufruf von grep erledigt werden.
quelle
Dies gibt die nächste Zeile nach dem regulären Ausdruck mit Perl aus
quelle