String in Text suchen und Satz ausgeben

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
BlackJack

Eine Lösung in C und ein Transkript eines Textlaufes auf dem C64. :-D

Code: Alles auswählen

#include <assert.h>
#include <ctype.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>

#define BUFFER_SIZE 1000


void skip_whitespace(FILE *f)
{
    int c;

    do {
        c = fgetc(f);
    } while (isspace(c) && c != EOF);
    
    if (c != EOF) ungetc(c, f);
}


void read_sentence(FILE *f, char *buffer)
{
    unsigned int i;
    int c;

    for (i = 0; i < BUFFER_SIZE - 1; ++i) {
        c = fgetc(f);
        if (c == EOF) break;
        *buffer++ = c;
        if (c == '.') break;
    }
    *buffer = '\0';
    assert(c == EOF || c == '.');
}


bool contains_word(char *string, char *word)
{
    char *tmp;
    unsigned int start_index, end_index;

    tmp = strstr(string, word);
    if (!tmp) return false;
    start_index = tmp - string;
    end_index = start_index + strlen(word);
    return (start_index == 0
            || !isalnum(string[start_index - 1]))
        && (end_index == strlen(string - 1)
            || !isalnum(string[end_index]));
}


int main(void)
{
    FILE *f;
    char sentence[BUFFER_SIZE];
    char *filename = "winter's tale";

    f = fopen(filename, "r");
    if (!f) {
        printf("could not open '%s'\n", filename);
        return 1;
    }
    while (!feof(f)) {
        skip_whitespace(f);
        read_sentence(f, sentence);
        if (contains_word(sentence, "Luzifer")) {
            puts(sentence);
        }
    }
    fclose(f);
    return 0;
}
Testlauf:
[codebox=text file=Unbenannt.txt]LOAD"$",8

SEARCHING FOR $
LOADING
READY.
LIST

0 "TEST-DISK " 00 2A
36 "123456789012 PIC" PRG
21 "TEST" PRG
26 "WINTER'S TALE" SEQ
581 BLOCKS FREE.
READY.
LOAD"TEST",8,1

SEARCHING FOR TEST
LOADING $0801 $1BEE
READY.
RUN
Dort trifft er auf seinen Boss Luzifer,
den Richter.
Pearly ersucht Luzifer um die Genehmigun
g, ausnahmsweise Zugang zu einer Adresse
ausserhalb der Stadt zu bekommen: zu Be
verlys Haus am See; der hohe Richter Luz
ifer lehnt Pearlys Antrag ab.
Pearly hat mit Luzifer einen Deal ausgeh
andelt: Wenn er bereit sei, sich sterbli
ch zu machen, duerfe er Peter auch ausse
rhalb der Stadt verfolgen.

ready.[/code]
nezzcarth
User
Beiträge: 1634
Registriert: Samstag 16. April 2011, 12:47

BlackJack hat geschrieben:@snafu: Schwierig. Insbesondere weil bei einigen Abkürzungen der Punkt gleichzeitig auch das Ende des Satzes sein kann. Wie bei ”usw.” wenn es am Satzende steht. [...] Natürliche Sprachen sind lustig. :-D
Wenn man es wirklich so elaboriert machen möchte, wäre der sauberere Weg m.M.n, einen Tokenizer für die die Zielsprache zu verwenden.
Das sieht dann z. B. so aus (https://www.linguistics.rub.de/~dipper/ ... nizer.html):

Code: Alles auswählen

$ cat text.txt                        
Am 23. Mai 1895 wird einem jungen Einwandererpaar auf Ellis Island die Einreise in die USA verweigert, weil beide an der Tuberkulose erkrankt sind. Als ihrem kleinen Sohn auch ohne sie die Einreise verweigert wird, beschließen sie, ihn in ein Modellsegelboot mit dem Namen Stadt der Gerechtigkeit zu setzen, in der Hoffnung, das Kind werde gefunden.
1916 ist das Kind zu einem Mann herangewachsen. Er nennt sich Dr. Peter Lake. Peter wurde von dem Gangsterboss Pearly Soames aufgezogen und verdient sich seinen Lebensunterhalt nun als Einbrecher und Dieb. Als Peter beschließt, Pearlys Bande und sein altes Leben zu verlassen, macht er sich seinen Ziehvater zum wütenden Gegner und wird von dessen Bande gejagt.

$ ./tokenize.pl -a abbrev.lex -y -t text.txt out.txt && cat out.txt
<?xml version="1.0" encoding="utf-8"?>
<text>
 <tok>Am</tok>
 <tok type='ord'>23.</tok>
 <tok>Mai</tok>
 <tok type='year'>1895</tok>
 <tok>wird</tok>
 <tok>einem</tok>
 <tok>jungen</tok>
 <tok>Einwandererpaar</tok>
 <tok>auf</tok>
 <tok>Ellis</tok>
 <tok>Island</tok>
 <tok>die</tok>
 <tok>Einreise</tok>
 <tok>in</tok>
 <tok>die</tok>
 <tok type='allCap'>USA</tok>
 <tok>verweigert</tok>
 <tok type='punc'>,</tok>
 <tok>weil</tok>
 <tok>beide</tok>
 <tok>an</tok>
 <tok>der</tok>
 <tok>Tuberkulose</tok>
 <tok>erkrankt</tok>
 <tok>sind</tok>
 <tok type='punc'>.</tok>
<sent_bound/>
 ...
 <tok>Er</tok>
 <tok>nennt</tok>
 <tok>sich</tok>
 <tok type='abbrev' source='listed'>Dr.</tok>
 <tok>Peter</tok>
 <tok>Lake</tok>
 <tok type='punc'>.</tok>
<sent_bound/>
...
NLTK und textblob bieten auch Tokenizer an.
Benutzeravatar
snafu
User
Beiträge: 6740
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Vielleicht insbesondere mal textblob-de anschauen. Auszug aus der Beschreibung:

Code: Alles auswählen

>>> from textblob_de import TextBlobDE as TextBlob
>>> text = '''Heute ist der 3. Mai 2014 und Dr. Meier feiert seinen 43. Geburtstag.
Ich muss unbedingt daran denken, Mehl, usw. für einen Kuchen einzukaufen. Aber leider
habe ich nur noch EUR 3.50 in meiner Brieftasche.'''
>>> blob = TextBlob(text)
>>> blob.sentences
[Sentence("Heute ist der 3. Mai 2014 und Dr. Meier feiert seinen 43. Geburtstag."),
 Sentence("Ich muss unbedingt daran denken, Mehl, usw. für einen Kuchen einzukaufen."),
 Sentence("Aber leider habe ich nur noch EUR 3.50 in meiner Brieftasche.")]
>>> blob.tokens
WordList(['Heute', 'ist', 'der', '3.', 'Mai', ...]
Benutzeravatar
kbr
User
Beiträge: 1487
Registriert: Mittwoch 15. Oktober 2008, 09:27

snafu hat geschrieben:Vielleicht insbesondere mal textblob-de anschauen.
Wie sich zeigt, ist das extrahieren von Sätzen aus komplexeren Texten alles andere als trivial. Vielleicht ist zumindest das ein gewisser Trost für den OP.
Benutzeravatar
snafu
User
Beiträge: 6740
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Habe es mal mit einem schnell zusammengeschriebenen Beispieltext gefüttert, wo wörtliche Rede in verschiedenen Formen enthalten ist. Ich bin kein Linguist, aber ich finde die Ergebnisse so wie ich es erwartet hätte. Wen's interessiert:

Code: Alles auswählen

In [12]: text = 'Er sagte: "Ich gehe ins Kino". Das tat er dann auch. "Das war eine großartige Idee", pflichtete Anna ihm bei als er wieder zuhause war. "Ich würde ja auch gerne. Aber ich muss lernen für die Prüfung." Das machte sie sehr traurig.'
In [13]: TextBlobDE(text).sentences
Out[13]:
[Sentence("Er sagte: "Ich gehe ins Kino"."),
 Sentence("Das tat er dann auch."),
 Sentence(""Das war eine großartige Idee", pflichtete Anna ihm bei als er wieder zuhause war."),
 Sentence(""Ich würde ja auch gerne."),
 Sentence("Aber ich muss lernen für die Prüfung.""),
 Sentence("Das machte sie sehr traurig.")]

In [14]: TextBlobDE(text).sentences[0].words
Out[14]: WordList(['Er', 'sagte', 'Ich', 'gehe', 'ins', 'Kino'])
Nur das Quoting ist eher ungewohnt und verwirrt den Python-Parser.
Antworten