Schrift
[thread]6505[/thread]

pattern matching: Loeschen eines  Textblocks aus einer Dat



<< |< 1 2 >| >> 15 Einträge, 2 Seiten
mkuehnl
 2004-08-17 11:55
#49327 #49327
User since
2004-08-17
5 Artikel
BenutzerIn
[default_avatar]
Hallo

ich moechte aus einer Textdatei einen Textblock loeschen.
Eine Zeile in diesem Textblock ist eindeutig so das ich diese finden kann.
Aber wie kann ich diese Zeile loeschen und die drei davor und die fuenf dahinter.

Gruß
pq
 2004-08-17 12:05
#49328 #49328
User since
2003-08-04
12208 Artikel
Admin1
[Homepage]
user image
am einfachsten mit Tie::File (welches u.U. aber performance-probleme hat)
ansonsten beschreib mal genauer, was du mit block meinst und ob es immer
genau 3 und 5 zeilen sind.
als tipp: datei zum lesen und schreiben öffnen, dann lesen bis zur gesuchten
stelle, 3 zeilen zurück seek()en (hier wirds komplizierter) und stelle merken,
8 zeilen überspringen, den rest einlesen,
wieder zurückseek()en, truncate und den rest schreiben.
Always code as if the guy who ends up maintaining your code will be a violent psychopath who knows where you live. -- Damian Conway in "Perl Best Practices"
lesen: Wiki:Wie frage ich & perlintro Wiki:brian's Leitfaden für jedes Perl-Problem
Dubu
 2004-08-17 12:08
#49329 #49329
User since
2003-08-04
2145 Artikel
ModeratorIn + EditorIn

user image
Dafuer sollte CPAN:Tie::File passend sein. Ist seit Perl 5.8.0 in der Standard-Distribution dabei.

Edit: pq war schneller. :)\n\n

<!--EDIT|Dubu|1092730124-->
mkuehnl
 2004-08-17 15:15
#49330 #49330
User since
2004-08-17
5 Artikel
BenutzerIn
[default_avatar]
hier ein Bsp .
Textdatei:

blablabla
blublublu
ahahahah

ertfdjgetgwqte
gtorjhqwtrjhiwq
optjhtpjhptqwr
ttttttttttttttttt
trwhkrtohor
trhokworth
hrtwophrt
hgtorwph

Die Zeile tttttttttt ist Eindeutig.
Diese Zeile muss ich finden und den kompletten Block loeschen, also die drei
Zeilen darüber und die 5 Zeilen darunter.

Markus
ptk
 2004-08-17 15:19
#49331 #49331
User since
2003-11-28
3645 Artikel
ModeratorIn
[default_avatar]
Genau das kannst du mit Tie::File machen. Die Beispiele in der SYNOPSIS der Tie::File-Dokumentation reichen eigentlich schon.
pq
 2004-08-17 15:53
#49332 #49332
User since
2003-08-04
12208 Artikel
Admin1
[Homepage]
user image
so, weil ich grad lust hatte:
Code: (dl )
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
use Fcntl qw(SEEK_SET);
open my $fh, "+<", "fileblock" or die $!;
my @store = (0,0,0);
my $tell = 0;
while(<$fh>) {
 if (m/^ttttt$/) {
   # zur gemerkten position seek()en
   seek $fh, $store[0], SEEK_SET;
   # zu löschenden block einlesen
   for (0..8) {
     <$fh>;
   }
   # rest einlesen
   my @rest = <$fh>;
   # wieder zurückkehren
   seek $fh, $store[0], SEEK_SET;
   # alles ab hier abschneiden
   truncate $fh, $store[0];
   # und den rest schreiben
   print $fh @rest;
 }
 else {
   # queue, die sich die positionen der letzten drei zeilen merkt
   shift @store;
   push @store, $tell;
 }
 $tell = tell $fh;
}
close $fh;

edit: seek mit Fcntl-konstante\n\n

<!--EDIT|pq|1092744513-->
Always code as if the guy who ends up maintaining your code will be a violent psychopath who knows where you live. -- Damian Conway in "Perl Best Practices"
lesen: Wiki:Wie frage ich & perlintro Wiki:brian's Leitfaden für jedes Perl-Problem
Crian
 2004-08-17 15:59
#49333 #49333
User since
2003-08-04
5866 Artikel
ModeratorIn
[Homepage]
user image
Ich würds noch einfacher machen: Die Datei einfach in einer while (<>) {...} Schleife durchdaddeln, dabei die letzten drei Zeilen merken und immer um vier Zeilen versetzt ausgeben (Du hast also immer vier Zeilen im Memory (modulo interner Blockverarbeitung).

Wenn Du auf Deine Zeile stößt, gibst Du die Zeilen im Speicher nicht aus, leerst die Variablen für die Zeilen und überliest auch noch die nächsten fünf, danach machst Du weiter wie gehabt. Dabei aufpassen, dass Du dann nicht aus Versehen leere Zeilen ausgibst.

Dürfte aber noch einfacher sein.

Also so (ungetestet, soll Skizze sein):

Code: (dl )
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#!/usr/bin/perl
use strict;
use warnings;

my @merk;

while (<>) {
    if (/^t+$/) {
        <>;
        <>;
        <>;
        <>;
        <>;
        @merk = ();
    }
    else {
         push @merk, $_;
    }
    if ($#merk >=3) {
        print shift @merk;
    }
}
print for @merk;
\n\n

<!--EDIT|Crian|1092744479-->
s--Pevna-;s.([a-z]).chr((ord($1)-84)%26+97).gee; s^([A-Z])^chr((ord($1)-52)%26+65)^gee;print;

use strict; use warnings; Link zu meiner Perlseite
mkuehnl
 2004-08-17 16:45
#49334 #49334
User since
2004-08-17
5 Artikel
BenutzerIn
[default_avatar]
ich habe deine Vorschlag ausprobiert.
Das script läuft durch aber die Zeilen sind noch in der Datei.
Es hat die Datei nicht geändert.
Hast du noch eine Idee
pq
 2004-08-17 16:54
#49335 #49335
User since
2003-08-04
12208 Artikel
Admin1
[Homepage]
user image
[quote=mkuehnl,17.08.2004, 14:45]ich habe deine Vorschlag ausprobiert.[/quote]
welchen?

edit: mein script ändert die datei, crians schreibt nur auf STDOUT und
ändert die datei nicht.\n\n

<!--EDIT|pq|1092747350-->
Always code as if the guy who ends up maintaining your code will be a violent psychopath who knows where you live. -- Damian Conway in "Perl Best Practices"
lesen: Wiki:Wie frage ich & perlintro Wiki:brian's Leitfaden für jedes Perl-Problem
Crian
 2004-08-17 16:59
#49336 #49336
User since
2003-08-04
5866 Artikel
ModeratorIn
[Homepage]
user image
Genau, meins ist (oder soll sein) ein Filter. Ich teste es mal gerade...

... klappt auf Anhieb :)

Code: (dl )
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
Microsoft Windows 2000 [Version 5.00.2195]
© Copyright 1985-2000 Microsoft Corp.

G:\privat\perl\forum>datei_zeilen_weg.pl testdatei.txt
blablabla
blublublu
ahahahah
kjkajnwbwhwd
qqwq
qerhetjz
zuuzu
ooop

G:\privat\perl\forum>cat testdatei.txt
blablabla
blublublu
ahahahah
kjkajnwbwhwd
ertfdjgetgwqte
gtorjhqwtrjhiwq
optjhtpjhptqwr
ttttttttttttttttt
trwhkrtohor
trhokworth
hrtwophrt
hgtorwph
lkjajklqw
qqwq
qerhetjz
zuuzu
ooop

G:\privat\perl\forum>


Die Zeile if (/^t+$/) { musst Du natürlich auf Deine Methode zur Erkennung der besonderen Zeile anpassen.

Mit

Code: (dl )
datei_zeilen_weg.pl testdatei.txt > testdatei_neu.txt


erhälst Du dann eine Datei ohne die entsprechenden Zeilen.

Pathologische Fälle sind noch nicht mit bedacht (es folgen keine füng Zeilen mehr in der Datei), könnten aber trotzdem gut gehen.

Der selbe Code wie oben nochmal optisch etwas kürzer:

Code: (dl )
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#!/usr/bin/perl
use strict;
use warnings;

my @merk;

while (<>) {
if (/^t+$/) {
<>; <>; <>; <>; <>;
@merk = ();
}
else {
push @merk, $_;
}
print shift @merk if $#merk >=3;
}

print for @merk;
\n\n

<!--EDIT|Crian|1092748409-->
s--Pevna-;s.([a-z]).chr((ord($1)-84)%26+97).gee; s^([A-Z])^chr((ord($1)-52)%26+65)^gee;print;

use strict; use warnings; Link zu meiner Perlseite
<< |< 1 2 >| >> 15 Einträge, 2 Seiten



View all threads created 2004-08-17 11:55.