2010-11-18 6 views
1

Ich bin auf der Suche nach Hilfe beim Erstellen eines Mustervergleichs zum Einlesen von E-Mails. Das Endziel ist eine eingehende Nachricht zu empfangen und nur die Antwortnachricht, die nicht alle den hinteren Junk (iV Fäden, Unterschrift, datastamp Header, etc ...)Suchen nach Ideen, wie man ein Muster anpasst, möglich oder nicht?

Hier sind die beiden gleichen Formate extrahieren:

Format 1:

The Message is here, etc etc can span a random # of lines 

On Nov 17, 2010, at 4:18 PM, Person Name wrote: 

lots of junk down here which we don't want 

Format 2:

The Message is here, etc etc can span a random # of lines 

On Nov 17, 2010, at 4:18 PM, Site <[email protected]> wrote: 

lots of junk down here which we don't want 

Format 3:

The Message is here, etc etc can span a random # of lines 

On Fri, Nov 19, 2010 at 1:57 AM, <[email protected]> wrote: 

lots of junk down here which we don't want 

Für beiden Beispiele oben, würde Ich mag ein Muster Spiel erstellen, die die erste Instanz der 2. Zeile findet. Und dann gibt nur was über diese Linie zurück. Ich möchte diese Trennlinie nicht.

Ich kann auf dem Datumsstempel nicht übereinstimmen, aber ich kann auf alles nach dem Komma abgleichen, da dies in meiner Kontrolle ist.

So ist die Idee, Sucht entweder eine dieser beide statischen Elemente:

, Site <[email protected]> wrote: 
, Person Name wrote: 

Und dann alles über dieser Position zu nehmen. Was denken Sie. Ist das möglich?

+2

"Ist das möglich?" Ja. Hast du es schon probiert? – meagar

+0

sollte wahrscheinlich erwähnt haben. Ich benutze Rails 3. also ist eine Rubin Methode ideal. – AnApprentice

+0

@meagar, das ist großartig. Ich war mir nicht einmal sicher! Ich bin ein Neuling, vielleicht kannst du ein paar Tipps geben, also habe ich eine Startrichtung? Ich bin noch nie so fertig. Ich habe vor einem Monat Ruby auf Schienen gelernt. – AnApprentice

Antwort

1

Nun wäre dies eine regexp Lösung sein:

/(On (?:(?:Sun|Mon|Tues|Wed|Thurs|Fri|Sat), |)(?:Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec) \d{1,2}, [12]\d{3}(?:|,) at \d{1,2}:\d{1,2} (?:AM|PM), (?:(?:Site |)<[\w.%+-][email protected][\w.-]+\.[A-Za-z]{2,4}>|Person \w+) wrote:)/ 

Sie zur Verfügung gestellt nur ein exemple so dass diese nicht perfekt sein könnten, aber es sollte ziemlich gut die Arbeit machen.

Dann müssen Sie die erste erfassten Gruppe mit $ 1 oder [0] erhalten, wenn Sie mit Spiel :)

regex = /(On (?:(?:Sun|Mon|Tues|Wed|Thurs|Fri|Sat), |)(?:Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec) \d{1,2}, [12]\d{3}(?:|,) at \d{1,2}:\d{1,2} (?:AM|PM), (?:(?:Site |)<[\w.%+-][email protected][\w.-]+\.[A-Za-z]{2,4}>|Person \w+) wrote:)/ 

if str =~ regex 
    puts "S1 : #{$1}" 
end 

if res = str.match(regex) 
    puts "S2 : #{res[0]}" 
end 

Btw, können Sie die Option /i auf der Regex verwenden.

+0

Was passiert, wenn die Monate nicht abgekürzt werden oder der Tag oder der abgekürzte Tag dem Monat vorangeht? –

+0

@Greg, solange die Regex die beiden Anwendungsfälle übertrifft, ist es gut für jetzt ... Was denkst du? – AnApprentice

+0

Worum geht es bei den if-Statements? – AnApprentice

2

Ich würde einen anderen Ansatz hinzufügen: Warum Sie nicht alles lesen und brechen, wenn Sie die Zeile, die Sie als Stop haben übereinstimmen?

+0

@Vp, danke ich mag den Push zurück! Das Problem ist der erste Teil dieser Zeile, der Datumsstempel, ist nicht etwas, gegen das ich weiß, es ist zufällig, es ist nur der Comman und nach "Site <[email protected]> schrieb:" was ist statisch und ich kann gegen übereinstimmen. Recht? – AnApprentice

+0

Das könnte funktionieren, aber ich drücke immer Vorsicht bei der Verarbeitung von Textdateien auf diese Weise aus, besonders wenn sie das Potenzial haben, groß zu sein. Wenn Sie Text auf diese Weise verarbeiten, sollten Sie ihn als Hintergrundprozess verwenden. – John

+0

Danke Ich bin offen für Vorschläge? – AnApprentice

1

Dies ist nicht eine gute Verwendung für Regex, wenn Sie versuchen, alles in einem Muster zu tun. Es ist möglich zu tun, aber ich vermute, dass das Universum abkühlen wird, bevor Sie alle Fehler beseitigen.

Um den Umfang dessen, was Sie versuchen zu verstehen, lesen Sie Wikipedia's article on "Posting Style". Es gibt viele verschiedene Möglichkeiten, wie Antworten in eine E-Mail-Nachricht eingebettet werden, die teilweise vom MUA (E-Mail-Benutzer-Agent) und teilweise von der antwortenden Person kontrolliert wird. Es gibt keine festgelegte Methode für die Zuweisung und keine Regel, die besagt, dass sich die Antwort in einem Block auf der Seite oder oben auf der Seite befindet. Dies bedeutet, dass jeder Code, den Sie schreiben, sehr ausgefeilt sein muss, um die Chance zu haben, konsistent zu arbeiten.

Haben Sie sich Mail angesehen? Es ist bereits geschrieben, es ist gut getestet, es hat alle möglichen coolen Schnickschnack, und es ist bereits geschrieben. (Ich sagte es noch einmal, weil neu erfassende Räder, die gut funktionieren, wirklich schmerzhaft sein können.)

Das Parsen von Nur-Text-E-Mail ist eine Aufgabe. Dann gibt es MIME-kodierte E-Mails mit unterschiedlichen Inhaltstypen. Dann gibt es "HTML" -E-Mails, die keine MIME-Blöcke haben, sondern stattdessen ein paar Idioten, die sich vorstellen, dass jeder HTML-Formatierung und blinkenden Text mag. Dann gibt es verschiedene merkwürdig zerbrochene Arten von Nachrichtentexten mit vier Antworttypen und den vollständigen Inhalt aller vorherigen Nachrichten, die unterhalb der nächsten angehängt sind, und die Unterschriften der schrecklich frustrierten Möchtegern-Schreiber, die den gesamten Text meines Lieblingsbuchs enthalten. " Girl to Grab ", AKA Vol. 5 der Enzyklopädie Britannica. Mail kann helfen, den ganzen Müll für Sie auszubrechen, Ihnen einen guten Schuss auf den Inhalt zu geben, den Sie brauchen.

Um eine Reihe von Text in einem Körper zu greifen, schauen Sie sich Rubys .. (AKA "Flip-Flop") -Operator an. Es wurde entwickelt, um ein Boolesches Wahr/Falsch zurückzugeben, wenn zwei verschiedene Tests auftreten. Siehe „When would a Ruby flip-flop be useful?

Normalerweise würde bauen Sie es mögen:

if ((string =~ /pattern1/) .. (string =~ /pattern2/)) 
    ... 
end 

Als Verarbeitung auftritt, wenn der erste Test passt etwas dann nachfolgende Schleifen wird in den if Block fallen. Wenn der Endungstest gefunden wird, wird der Block für nachfolgende Schleifen ausgeschaltet. In diesem Fall möchten Sie entweder ein Zeichenfolgenliteral oder einen kleinen Regex verwenden, um Ihre Start- und Endzeilen zu finden. Wenn Sie das Startmuster im späteren Text sehen können, müssen Sie herausfinden, wie Sie das fangen können.

Zum Beispiel, hier ist ein Weg, um einige Inhalte zu ergreifen, die Ihre angegebenen Anforderungen gerecht zu werden scheinen, wenn jemand hat eine Top-Antwort:

msg = <<EOT 
The Message is here, etc etc can span a random # of lines 
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod 

On Nov 17, 2010, at 4:18 PM, Person Name wrote: 

Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod 
EOT 

body = [] 
msg.lines.each do |li| 
    li.chomp! 
    body << li 
    break if (li =~ /^On (\S+)*\w+ \d+, \d+, at [\d:]+ \w+, .+ wrote:/i) 
end 
puts body[0 .. -2] 

puts '=' * 40 

msg = <<EOT 
The Message is here, etc etc can span a random # of lines 
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod 

On Nov 17, 2010, at 4:18 PM, Site <[email protected]> wrote: 

Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod 
EOT 

body = [] 
msg.lines.each do |li| 
    li.chomp! 
    body << li 
    break if (li =~ /^On (\S+)*\w+ \d+, \d+, at [\d:]+ \w+, .+ wrote:/i) 
end 
puts body[0 .. -2] 

Und hier ist der Ausgang:

# >> The Message is here, etc etc can span a random # of lines 
# >> Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod 
# >> 
# >> ======================================== 
# >> The Message is here, etc etc can span a random # of lines 
# >> Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod 
# >> 

Die Muster könnte einfacher sein, aber wenn es war, würde es die Chance erhöhen, falsch-positive zurückzugehen.

+1

ich sehe nicht, warum das war downvoted? – scaney

+0

Ich entweder. Offensichtlich hatte jemand Angst, warum auch zu sagen. –

Verwandte Themen