PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Script das Maillisten filtert (kniffelig)



SeeksTheMoon
28-06-2004, 15:41
Ich empfange eine CVS-Mailingliste, d.h. ich bekomme viele Mails in denen das gleiche drin steht. Ich will alle Duplikate rauswerfen und jeweils nur eine Mail übrig lassen.
Das Problem ist, dass diese Mails nicht 100% identisch sind, sondern dass nur eine Textpassage in den Mails gleich und der Rest (der mich nicht interessiert) verschieden ist

So sehen die Mails aus:


Update of /cvsroot/blabla
in directory blabla

Log Message:
"Wilder Text"

Index: bla.cpp
===========================

<hier steht ein diff der Datei bla.cpp>


-----------------------------------
<hier kommt Sourceforge-Werbung>


Ich müsste also ein Shell oder Perl-Script haben, das den Text zwischen "Log Message:" und "Index:" rauspuhlt weil das die Stelle ist die mich interessiert.
Wenn mir jemand verraten kann wie man das am besten macht, das wäre schonmal super.

Als Mailprogramm verwende ich kmail, dort kann ich für jede Mail ein externes Programm aufrufen lassen (also das Script).
Wie man das Vergleichen und Löschen am besten macht, da hab ich noch keine gute Idee.
Eine Möglichkeit wäre es bei jeder einkommenden Mail in /tmp eine Datei mit der Textpassage abzulegen, bzw zu vergleichen ob es den Text schon in einer Datei gibt.
Das Löschen könnte man dann über DCOP machen...
Hat jemand ne bessere Idee?

Badsteve
28-06-2004, 17:56
hi,

ne kleine Idee von mir. Du nimmst dir einfach den Text den du brauchst, dann erstellst du davon ne md5sum, sicherst die in einer Datenbank .. . mit perl kann man das irgendwie mit hashes und tie machen. Und dann guckst du, ob es die Summe schon gibt. Wenn ja Mail weg, sonst neu Summe in die Datenbank speichern.
Wenn ich Zeit hab, dann versuch ich mal mein Glück, aber sieht schlecht aus .. ;) Du bekommst das aber auch hin.

steve

SeeksTheMoon
28-06-2004, 18:11
hm, die md5sum würde mir das Vergleichen erleichtern, aber eine Datenbank ist eine Spur zu krass.

fs111
28-06-2004, 21:05
Ich bin nicth so der Perl-Kenner, aber vermutlich wird es eine Möglichkeit geben Hashes direkt auf der Platte zu speichern. In Python geht das zumindest mit shelve sehr gut. Da der Hash ja von Haus aus keine doppelten Einträge erlaubt, wäre damit die Sache vom Tisch.

fs111

Badsteve
28-06-2004, 21:33
in Perl geht das mit db_file



tie(%hash, "DB_File", $filename) or die;


dann kann ganz nochmal aus dem %hash gelesen werden und änderungen werden direkt in die Datei übertragen. "untie %hash" um den Vorgang zu beenden.

steve

peschmae
28-06-2004, 21:36
Also den Text zwischen dem Log Message und dem Index kriegst du mit sed recht gut raus. Dann machst du was in die Richtung:


#!/bin/bash
DATEI=/die/Mail
SUMS=/checksum.txt
TEXT=$(sed -n "/Log Message/,/Index/ p" < $DATEI | grep -v Index)
MD5=$(echo $TEXT | md5sum| sed s/\ .*//)
touch $SUMS

if grep -q $MD5 $SUMS; then
echo nix da
else
echo da ist ja neu
echo $MD5 >> $SUMS
fi


So.

MfG Peschmä

SeeksTheMoon
30-06-2004, 11:05
ah, das sieht sehr gut aus. Ich hab das jetzt wie folgt gemacht:
Bei KMail kann man eine Mail durch ein Programm leiten:
/pfad/zu/filterscript %0
Startet das Filterscript und schiebt dort den ganzen Mailtext rein.

Das Filterscript habe ich etwas geändert, weil die Mails nicht in Dateien gespeichert werden, sondern mit %0 direkt übergeben werden:

#!/bin/bash
SUMS=~/Mail/checksummen/checksum.txt
TEXT=$(echo $1 | sed -n "/Log Message/,/Index/ p")
MD5=$(echo $TEXT | md5sum| sed s/\ .*//)
touch $SUMS

if grep -q $MD5 $SUMS
then
echo "DELETE ME PLEASE"
else
echo $MD5 >> $SUMS
fi
Alle Ausgaben die das Script macht, überschreiben den nachrichtentext. Ein zweiter Filter prüft dann hinterher ob im Nachrichtentext DELETE ME PLEASE steht und löscht diese Mails direkt.
Auf der Konsole klappts, jetzt muss ich mal abwarten bis der nächste Schwall an Mails kommt.
Vielen Dank schonmal.

Achso, noch eine Frage: Ist touch $SUMS wirklich nötig?

peschmae
01-07-2004, 09:51
Das touch verhindert dass Grep beim ersten Aufruf - also wenn die Datei noch nicht da ist - sowas ausgibt:


grep: sumfile: Datei oder Verzeichnis nicht gefunden


Ist aber nicht so wichtig.

MfG Peschmä

SeeksTheMoon
01-07-2004, 10:17
ich hab noch ein Problem gefunden:
Wenn ich die Mails durch das Script leite, dann muss es von einer Pipe lesen können. Ich hab mich schon gewundert warum alle mails gekillt werden :D

Das Lesen von einer Pipe geht ja so:

TEXT=""

while read LINE
do
TEXT=$TEXT$'\n'$LINE
done
echo $TEXT

Aber an der Stelle '\n' macht er einfach kein Newline; ich hab schon alles mögliche versucht: Echo in Backticks, Zuweisen von \n auf eine Variable, ...
Irgendwie wird der ganze Text immer in eine Zeile geschrieben.

roli
01-07-2004, 14:28
versuch es mal mit der Zuweisung:
TEXT="$TEXT$\n$LINE"
und der -e Option bei echo:
echo -e $TEXT
oder alternativ:
echo -e "$TEXT"

SeeksTheMoon
01-07-2004, 16:10
hab noch was nachgestöbert; man muss die Variable bei der Ausgabe schützen wenn Leerzeichen drin sind.

Das Script sieht jetzt so aus und scheint zu funktionieren:


#!/bin/bash

#
# pipe through
# This will feed the message to a program. If that program returns output,
# the entire message (including the headers) will be replaced with this output.
# If the program does not return output or exits with a return code that's not 0,
# the message will not change. Specify the full path to the program.
# Warning
# Be cautious with this action, as it will easily mess up your messages if the
# filter program does return garbage or extra lines.
#


SUMS=/home/mark/Mail/mailfilter/checksum.txt
TEXT=""

while read LINE
do
TEXT="$TEXT\n$LINE"
done

if echo -e $TEXT | grep -q "\-\-\- NEW FILE:"
then
TEXT=$(echo -e $TEXT | sed -n "/^Log Message:/,/^--- NEW FILE:/ p"| sed "/^--- NEW FILE:/d")
else
TEXT=$(echo -e $TEXT | sed -n "/^Log Message:/,/^Index:/ p" | sed "/^Index:/d")
fi
MD5=$(echo "$TEXT" | md5sum| sed s/\ .*//)
touch $SUMS

if grep -q $MD5 $SUMS
then
echo "DELETE ME PLEASE"
else
echo $MD5 >> $SUMS
#echo -e "$TEXT"
fi