Mustererkennung in Texten - Textblöcke separieren
Bruno
- perl
0 K@rl0 Matti Maekitalo0 Mustererkennung
Bruno0 Klaus Mock0 Bruno
hallo liebe forumgemeinde und perl freaks,
ich lese nun schon sehr lange in diesem forum und habe hier schon oft interessante problemlösungen gefunden.
heute allerdings möchte ich euch das erste mal bitten mir zu helfen - ich habe im moment eine kleine "hirnblockade" :)
das problem:
mein script liesst ein word-dokument per OLE aus und stopft den inhalt in ein array.
wenn ich mir dieses array mittels "foreach" ansehe, dann sieht es so aus, wie der auszug weiter unten.
ich möchte jetzt die einzelnen textblöcke weiter verarbeiten.
also jeder dieser blöcke hat eine überschrift und eine beschreibung.
getrennt werden die blöcke mit leerzeilen, manchmal auch einige hintereinander (im beispiel zu sehen).
kann mir bitte jemand eine kleine routine zeigen (oder ansatzpunkte), welche mir block für block zur weiterverarbeitung zur verfügung stellt?
wichtig ist, das die leerzeilen sauber erkannt und als trenner benutzt werden.
in den übergebenen blöcken sollen dann allerdings keine leerzeilen mehr sein.
für eure hilfe möchte ich mich jetzt schon bedanken!!!
viele grüße,
bruno
------------------------------------------------------------------
Nicht von dieser Welt
Italien 1999 100' R: Giuseppe Piccioni
D: Margherita Buy, Silvio Orlando, Carolina Freschi
Brot und Tulpen
Italien 2000 F 118' R: Silvio Soldini
D: Licia Maglietta, Bruno Ganz, Giuseppa Battiston
Ayurveda
D/Indien 2000 F 102' R: Pan Nalin
Der Film bietet eine intensive und sehr sinnliche Reise...
Mio, mein Mio
SU/Schweden/Norwegen 1987 F 95'
Phantasievoll und spannend sind die Abenteuer, die der 9jährige...
------------------------------------------------------------------
Hallo Bruno
Nicht von dieser Welt Italien 1999 100' R: Giuseppe Piccioni D: Margherita Buy, Silvio Orlando, Carolina Freschi
Brot und Tulpen Italien 2000 F 118' R: Silvio Soldini D: Licia Maglietta, Bruno Ganz, Giuseppa Battiston
Ayurveda D/Indien 2000 F 102' R: Pan Nalin Der Film bietet eine intensive und sehr sinnliche Reise...
Jede Zeile ist ein element in einem Array? wenn ja + sagen wir, es ist das Array @a, dann erst mal einen String draus machen:
my $s = join('', @a);
dann Splitten mit mindestens zwei Leerzeilen als Seperator:
my @splitted = split(/\n\n+/, $s); oder kompakter: my @splitted = split(/\n\n+/, join('', @a));
in @splitted steht jetzt jeweils ein Block als String (also mit Zeilenumbrüchen), also:
$splitted[0] ist: "Brot und Tulpen Italien 2000 F 118' R: Silvio Soldini D: Licia Maglietta, Bruno Ganz, Giuseppa Battiston" (sollte zumindest sein ;)
das kannst du dann weiter splitten z.B.
my @item_splitted = split(/n/, $splitted[$i]); z.B. $item_splitted[1] ist dann "Italien 2000 F 118' R: Silvio Soldini"
Mit einem herzlichen RTFM! (man perlfunc)
K@rl
PS:
... wieder was vergessen:
ich gehe davon aus, daß jedes Element in @a ein abschließendes Newline "\n" hat - auch die leeren Zeilen; wenn nicht, dann ändern:
my $s = join("\n", @a);
hallö k@rl,
klapp nicht... nicht so richtig :(
-122 elemente werden ins array gepackt
-jedes hat ein \n
dein routinchen bringt mit erkennung von zwei leerzeilen den kompletten inhalt des ausgangs-arrays.
mit einem \n weniger zumindest weniger - aber nicht richtig.
es ist für mich schwierig eine genaue beschreibung abzuliefern, sorry.
könnte ich vielleicht den inhalt des word-dokumentes statt ins array in eine datei schreiben und dir schicken?
das würde den vorteil haben, das du den gesamten inhalt siehst - ich kann es hier ja nicht so recht posten :)
viele grüße,
bruno
ps: diese sache ist für mich sehr wichtig, denn das programm soll schnellstens fertig werden (ist wohl meistens so).
den ersten teil des programms habe ich schon fertig und es läuft wunderbar. dort wird eine excel-tabelle ausgelesen und alle daten (datum, uhrzeit, filmtitel) werden sauber in eine html-datei sortiert und geschrieben. das ich jetzt bei so einer text-geschichte auch noch verblöde.... nee nee ;)
hallo liebe leute,
ich habe hier mal einen längeren auszug des textes als .ZIP file zum download gelinkt.
damit ist mein problem vielleicht besser verständlich.
http://217.199.17.184/kino.zip
ich hoffe immer noch auf eure hilfe :->
viele grüße,
bruno
man bin ich blöd!
das war ein zahlendreher - hier der richtige link:
http://217.199.71.184/kino.zip
Hallo Bruno
also, normalerweise mach' ich sowas ja nicht ...
Das Problem liegt in Deinen Eingabedaten!! Sieh Dir mal die Datei mit einem Hex-Editor an und Du wirst feststellen, daß Du teilweise (immer?) am Zeilenende "\x0d\x0d\x0a" mit zum Teil vorangestellten Schrott hast :-((
Das hier Funktioniert bei mir (WinDOS Maschine mit ActivePerl):
1. use strict; 2. my $infile = $ARGV[0] || "kino.txt"; 3. open FH, "$infile" or die "cannot open $infile - $!"; 4. binmode FH; 5. my @in = <FH>; # slurp! 6. close FH;
7. # -- clean the \0d\0d\a... mess ... 8. my @cleaned; 9. foreach (@in) { 10. s/\s+$/\n/; 11. push @cleaned, $_; 12. } 13. undef @in; # not needed anymore -> free some RAM 14. # -- END clean
my $joined = join('', @cleaned);
my @splitted = split(/\n\n+/, $joined);
undef $joined; # not needed anymore -> free some RAM
my $i = 0;
foreach (@splitted) {
21. printf "%4d:: %s\n\n", $i++, $_;
22. }END-OF-RECORD
Beachte:
Zeile 3: möglicherweise wird das o-p-e-n im Forum irgendwie als "/pen" dargestellt Zeile 4: binmode - wegen des Schrotts .. Zeilen 7-14: hier wird der Schrott entfernt - gibt sicher elegantere Wege das zu tun, aber es macht Zeilen 15-17: wie gesagt - bei sauberen Eingabedaten ist das ein Weg (remember: TIMTOWTDI!) - oder 15+16 in einem Befehl - wie vorher im Thread beschrieben
In @splitted stehen die jeweiligen Records. Beachte, daß zwar innerhalb jedes Records Zeilenumbrüche "\n" vorhanden sind, welche die Zeilen trennen, aber am Ende kein "\n" steht (was Dir beim Weiterverarbeiten eher nutzen sollte).
Die ersten beiden Records sind dann bei mir als Output des Tests (möglicherweise werden hier im Forum Deine Deutschen Hoch-Tief-Anführungsstriche nicht richtig dargestellt):
0:: Nicht von dieser Welt Italien 1999 100' R: Giuseppe Piccioni D: Margherita Buy, Silvio Orlando, Carolina Freschi Auf der Suche eines Findelkindes kommen sich ein menschenscheuer Wäschereibesitzer und eine idealistische katholische Ordensschwester langsam näher. Am Ende haben die beiden nicht nur die Mutter, sondern auch noch sich selbst gefunden. - Eine Geschichte mit emotionaler Kraft und komödiantischer Leichtigkeit. „Herzergreifende Geschichten im Stile des Neorealismus - Giuseppe Piccionis kleines Meisterwerk scheint dort anzuschließen, wo ‚Brot und Tulpen' aufhört.“ (Frankfurter Rundschau) „Ein kleines Juwel ... völlig zu Recht mit internationalen Auszeichnungen überhäuft.“ (Filmecho) „... erstaunlich ... bewegend. ‚Nicht von dieser Welt' hat genug Klugheit, Feingefühl und Herz für jeden, der ‚Brot und Tulpen' liebt.“ (Der Spiegel) Nominierung für den Oscar „Bester nicht englisch-sprachiger Film“ 2000.
1:: Brot und Tulpen
Italien 2000 F 118' R: Silvio Soldini
D: Licia Maglietta, Bruno Ganz, Giuseppa Battiston
Als Rosalba, eine Hausfrau aus Pescara, an einer Raststätte den Bus verpaßt und Mann und Söhne sie erst nach einiger Zeit vermissen, beginnt für sie ein neues Leben. Per Anhalter landet sie in Venedig, wo sie bei einem etwas verschrobenen, aber liebenswerten Schöngeist und Kellner nicht nur eine billige Bleibe, sondern allmählich auch Zuneigung findet. - Der Film ist nahezu mit allen Preisen ausgezeichnet worden, die Italien zu bieten hat. Aber auch hierzulande sind Publikum und Kritik in ihrer Wertschätzung einer Meinung.
„Am Ende ... ist jeder glücklich. Vor allem der Zuschauer.“ (FAZ)
„... wunderschön. Und liebevoll. Und sehr komisch.“ (Die Welt)
„... romantische Komödie von klassischem Format.“ (Der Tagesspiegel)
~~~~END-OF-RECORD~~~~
Gute Nacht!
K@rl
PS: "GIGO" steht für "Garbage In - Garbage Out"
PPS: "Amelie" halte ich für einen überbewerteten Film
moin k@rl,
juuuubel!!! es geht - ich könnt dich knutschen :>
wow - werd ich jetzt gut schlafen...
also, normalerweise mach' ich sowas ja nicht ...
...sieh es als tägliche gute tat an *g*, ich wäre dran fast verzweifelt!
Das Problem liegt in Deinen Eingabedaten!!
Sieh Dir mal die Datei mit einem Hex-Editor
an und Du wirst feststellen, daß Du teilweise
(immer?) am Zeilenende "\x0d\x0d\x0a"
mit zum Teil vorangestellten Schrott hast :-((
...das hat das Win32::OLE modul produziert - sorry :(
PPS: "Amelie" halte ich für einen überbewerteten Film
:)))))
ich habe diese kritiken zum glück nicht geschrieben.
yo k@rl, dann danke ich dir nochmals recht herzlich für die freundliche und sehr schnelle hilfe.
auch allen anderen, die mir helfen wollten gilt mein dank!
viele grüße aus berlin und allen eine gute nacht,
bruno
use Mosche;
kann mir bitte jemand eine kleine routine zeigen (oder ansatzpunkte), welche mir block für block zur weiterverarbeitung zur verfügung stellt?
wichtig ist, das die leerzeilen sauber erkannt und als trenner benutzt werden.
in den übergebenen blöcken sollen dann allerdings keine leerzeilen mehr sein.
Mein Ansatz geht davon aus, dass ein eintelner Block in drei hintereinander folgenden Zeilen steht (nur zw. den Blöcken Leerzeilen, nicht im Block).
Er macht grundsätzlich folgendes:
er liest aus deinem Array ein.
Wenn er eine Spalte ohne Text erwischt, überspringt er sie.
Ansonsten hat er die erste Zeile.
Dann liest er noch zwei Zeilen ein, und hat damit den kompletten Block. danach gehts weiter.
my @block;
while(defined(my $line = shift @lines)) {
my %eintrag;
next if $line =~ m/^\s*$/; # leere Zeilen überspringen
# Zeilen, die nichts als
# Leerzeichen und Tabs enthalten
# Wenn wir hier sind, haben wir die Überschrift
$eintrag{'titel'} = $line;
# das hier musst du machen,
# wird nen komplizierter regex.
# ich weiss nicht, nach welchen
# Kriterien du das ordnen willst.
my ($land, $jahr, ...) = split(/\s+/, shift @lines);
# jetzt die dritte Zeile (Darsteller)
$eintrag{'darsteller'} = shift @lines;
}
use Tschoe qw(Matti);
hallo matti & k@rl,
ihr seit ja fix - hut ab und vielen dank für das hirnfutter!
werd gleich mal ein paar tests machen...
matti, die blöcke bestehen leider nicht aus 3 zeilen.
das dokument ist 3 meter lang und jeder block 10 bis 30 zeilen :)
so denn, ich mach dann mal.
liebe grüße,
bruno
Hallo,
das problem:
mein script liesst ein word-dokument per OLE aus und stopft den inhalt in ein array.
ich würde gleich beim Einlesen die Aufteilung machen. Etwa
<code>
my $block_count = 0;
my @blocks;
my $line
while(&get_line_from_worddocument($line))
{
chomp; # Frage: ist \n wirklich Bestandteil der Zeilen?
$line =~ s/\s*$//; # eventuell Leerzeichen rausschmeißen
if($line eq '')
{
$block_count++;
}
else
{
push @{$blocks[$block_count]}, $line;
}
}
</code>
Damit ersparst Du Dir zumindest ein Array, daß eigentlich nur einmal gebraucht wird.
'Literaturhinweis':
perldoc perllol
perldoc perldsc
Grüße
Klaus
moin klaus,
vielen dank für deine hilfe - habs gerade ausprobiert.
leider auch nicht das richtige.
zumindest passiert folgendes bei mir:
-leerzeilen werden rausgenommen (ok)
-jede zeile mit inhalt stellt jetzt ein element im array dar :(
es soll ja jeder block (der durch leerzeilen getrennt ist/war) ein element sein.
anbei nochmal ein auszug des textes, der bearbeitet werden soll zum download:
http://217.199.71.184/kino.zip
viele grüße,
bruno