Schrift
[thread]10253[/thread]

Zeile in Datei bearbeiten

Leser: 5


<< |< 1 2 >| >> 13 Einträge, 2 Seiten
hudo
 2007-08-29 14:02
#98813 #98813
User since
2003-11-20
72 Artikel
BenutzerIn
[default_avatar]
Hallo,

es sind Einträge folgenden Formats in einer Datei:
Code: (dl )
1
2
3
----0---m---28.07.2007---23:13:18---rest---id=123456
----9---a---28.07.2007---23:13:46---rest---id=345677
----0---a---28.07.2007---23:13:57---rest---id=876543

Bei einem Vergleich mit zu bearbeitenden ID (zB id=345677 ), moechte ich bei der entsprechenden Zeile den Zaehler
erhöhen, hier von 9 auf 10 und die aktuelle Zeit setzen.
Beim Zaehler ist noch zu beachten, das er jetzt zweistellig wird, das Ergebnis sollte so aussehen:
Code: (dl )
---10---a---29.07.2007---13:32:46---rest---id=345677


Wie macht man das am geschicktesten ?

Das ist mein Code um den Zeitstempel zu definieren:
Code: (dl )
1
2
3
4
5
6
7
8
9
###  timestamp##################################
( $sec ,$min ,$hour ,$mday ,$mon ,$year ) = localtime;
$jahr = 1900+$year;
if ( $mon <= 9 ) {$mon = "0"."$mon";}
if ( $mday <= 9 ) {$mday = "0"."$mday";}
if ( $sec <= 9 ) {$sec = "0"."$sec";}
if ( $min <= 9 ) {$min = "0"."$min";}
if ( $hour <= 9 ) {$hour = "0"."$hour";}
### ende timestamp##################################
pktm
 2007-08-29 14:34
#98815 #98815
User since
2003-08-07
2921 Artikel
BenutzerIn
[Homepage]
user image
Na, funktioniert es denn? So auf anhieb fehlen mir da nur die Kommentare, warum du formatierst (wenn jemand deinen Quellcode liest hat er nicht deine Ideen oder eine zu bearbeitende Datei im Kopf).

Eventuell bringt es dir was, wenn du dir den Befehl sprintf anschaust (der steht auch in der perlfunc manpage bei localtime).
http://www.intergastro-service.de (mein erstes CMS :) )
RPerl
 2007-08-29 15:19
#98821 #98821
User since
2006-11-26
384 Artikel
BenutzerIn

user image
Code (perl): (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
#!/usr/bin/perl

use warnings;
use strict;
#use kopfschmerzen;

my $string = '----9---a---28.07.2007---23:13:46---rest---id=345677';
my $regexp = '----(\d+)---\w+---(\d+.\d+.\d+)---(\d+:\d+:\d+)---rest---id=(\d+)';
my ($count, $date, $time, $id);


$string =~ /$regexp/i;

$count = $1;
$date = $2;
$time = $3;
$id = $4;

if( $id == 345677 ) {
        $count += 1;
        $date = localtime(); 
        $time = localtime();
        
        print "----$count---a---$date---$time---rest---id=$id";
}


Fuer das mit den timestamps wuerde ich mal auf renee warten...
Oder halt mal Time::Format checken.

Ich hoffe das hilft..

Gruß,

rPerl
bloonix
 2007-08-29 15:44
#98825 #98825
User since
2005-12-17
1615 Artikel
HausmeisterIn
[Homepage]
user image
ein kleines Beispiel (bitte mit Testdaten ausprobieren) ...
und vorausgesetzt, dass die Zeilen wirklich eine fixe Länge
haben!

# cat test.txt
----0---m---28.07.2007---23:13:18---rest---id=123456
----7---a---28.07.2007---23:13:46---rest---id=345677
----0---a---28.07.2007---23:13:57---rest---id=876543
----8---a---28.07.2007---23:14:57---rest---id=876544
----0---a---28.07.2007---23:15:57---rest---id=876545
----9---a---28.07.2007---23:16:57---rest---id=876546


Code (perl): (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
34
35
36
37
38
39
40
41
42
43
44
45
46
use strict;
use warnings;

my $len = 53; # Zeilenlänge
my %nmb =     # Nummern, die geändert werden sollen
    map { $_ => undef } (7, 8, 9); 

open my $fh, '+<', 'test.txt' or die $!; 

while ( my $line = <$fh> ) { 
    my $nmb = substr($line, 0, 5);  # die ersten 5 Zeichen
    $nmb =~ s/^-+//g;               # Bindestrich entfernen
    if (exists $nmb{$nmb}) {        # wenn die Zeile geändert werden soll
        my $pos = tell($fh);        # Position des Zeilenendes merken
        seek($fh, $pos - $len, 0);  # Zum Anfang der Zeile springen
        $nmb = sprintf('%5s', 10);  # Kontainer
        $nmb =~ tr/ /-/;            # Leerzeichen ersetzen
        print $fh $nmb;             # erste Spalte ersetzen
        # nun befinden wir uns an Position 5

        # Datum + Uhrzeit
        my ($sec,$min,$hour,$mday,$mon,$year) = localtime;
        $year += 1900;
        $mon  += 1;

        # zu Position 9 springen, da wo das Datum anfängt und Datum + Uhrzeit schreiben
        seek($fh, 4, 1); 
        print $fh sprintf('---%02d.%02d.%04d', $mday, $mon, $year);
        print $fh sprintf('---%02d:%02d:%02d', $hour, $min, $sec);

        # zur Position springen, wo die ID anfängt
        seek($fh, 7, 1); 

        # die ID Filtern, +1, Kontainer erzeugen, Leerzeichen ersetzen
        my $id = substr($line, 40, 12);
        $id =~ s/^-*id=//;
        $id = sprintf('%12s', "id=" . ++$id);
        $id =~ tr/ /-/;
        print $fh $id;

        # zum gemerkten Zeilende springen, dass ist hinter dem Newline
        seek($fh, $pos, 0); 
    }   
}

close $fh;


# cat test.txt
----0---m---28.07.2007---23:13:18---rest---id=123456
---10---a---29.08.2007---13:43:40---rest---id=345678
----0---a---28.07.2007---23:13:57---rest---id=876543
---10---a---29.08.2007---13:43:40---rest---id=876545
----0---a---28.07.2007---23:15:57---rest---id=876545
---10---a---29.08.2007---13:43:40---rest---id=876547
What is a good module? That's hard to say.
What is good code? That's also hard to say.
One man's Thing of Beauty is another's man's Evil Hack.
bloonix
 2007-08-29 15:46
#98826 #98826
User since
2005-12-17
1615 Artikel
HausmeisterIn
[Homepage]
user image
RPerl+2007-08-29 13:19:20--
Code (perl): (dl )
1
2
3
my $string = '----9---a---28.07.2007---23:13:46---rest---id=345677';
my $regexp = '----(\d+)---\w+---(\d+.\d+.\d+)---(\d+:\d+:\d+)---rest---id=(\d+)';
my ($count, $date, $time, $id);

das wird so nicht funktionieren, denn es scheinen Spalten mit fixer breite zu sein.
es kann also sein, dass die erste Spalte zum Beispiel so ausschaut:

----1
---10
--100
-1000
10000
What is a good module? That's hard to say.
What is good code? That's also hard to say.
One man's Thing of Beauty is another's man's Evil Hack.
RPerl
 2007-08-29 16:17
#98828 #98828
User since
2006-11-26
384 Artikel
BenutzerIn

user image
Hab in seinen dummies davon nichts gesehen.
bloonix
 2007-08-29 16:23
#98829 #98829
User since
2005-12-17
1615 Artikel
HausmeisterIn
[Homepage]
user image
RPerl+2007-08-29 14:17:49--
Hab in seinen dummies davon nichts gesehen.


schau mal in sein Beispiel:

----9---a---28.07.2007---23:13:46---rest---id=345677
...
---10---a---29.07.2007---13:32:46---rest---id=345677


deshalb bin ich davon ausgegangen, dass es Spalten mit fester
Länge sind.

----9 = 4 x -
---10 = 3 x -
What is a good module? That's hard to say.
What is good code? That's also hard to say.
One man's Thing of Beauty is another's man's Evil Hack.
RPerl
 2007-08-29 16:49
#98830 #98830
User since
2006-11-26
384 Artikel
BenutzerIn

user image
sieht wohl tatsaechlich so aus.. sorry

//e: haette es in etwa so geloest wie Du...
hudo
 2007-08-29 18:52
#98843 #98843
User since
2003-11-20
72 Artikel
BenutzerIn
[default_avatar]
Hallo Leute,

vielen Dank fuer die vielen und schnellen Anregungen.
Muss kurz klarstellen, die Records haben NICHT fixe Laenge.

Ich wollte eigentlich auch wissen, obs besser ist die Datei einzulesen mit open usw
oder mit Tie::File direkt in der Datei zu bearbeiten.

Dann nochwas, hab mit sowas angefangen:
Code: (dl )
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
	if ( -s $file ) {
print "\n Hole aus : $file\n";
open(DATEI,"<$file") or die $!;
@adressen = <DATEI>;
close DATEI;
}

foreach $elem (@adressen) {
foreach $elem2 (@sel_ids) { ## array with id's to process
if ( $elem =~ $elem2 ) {
## hier Erhoehung des counters in $elem und neue timestamp

}
}
}


Kann man eigentlich $elem direkt editieren und sind die Aenderungen dann in @adressen
uebernommen ? Ich denke es waere besser die äussere Schleife mit Zaehler bis $#adressen laufen zu lassen und dann das adressen[zaehler] zu editieren.

sid burn
 2007-08-29 19:29
#98846 #98846
User since
2006-03-29
1520 Artikel
BenutzerIn

user image
Quote
Ich wollte eigentlich auch wissen, obs besser ist die Datei einzulesen mit open usw
oder mit Tie::File direkt in der Datei zu bearbeiten.

Also bevor du die Datei einliest und in einen kompletten Array Speicherst sollte man lieber Tie::File nutzen. Da dort die ganze Datei nicht in den Speicher geladen wird.

Ansonsten kannst du eine Datei mit open öffnen mit einer while() Schleife die zeilen durchgehen und sofort in eine neue Datei schreiben. Danach dann die erste datei löschen, und die neue Datei den namen der alten Datei geben.

Das ist auch das vorgehen was perl mit dem Schalter "-i" macht, bzw wenn du die Variable "$^I" setzt.

Quote
Kann man eigentlich $elem direkt editieren und sind die Aenderungen dann in @adressen

Ja kannst du.

Code (perl): (dl )
1
2
3
for my $elem ( @array ) {
    # Verändere $elem
}


Jede veränderung an $elem wirkt sich auf @array aus, das ist auch so gewollt.

Quote
Ich denke es waere besser die äussere Schleife mit Zaehler bis $#adressen laufen zu lassen und dann das adressen[zaehler] zu editieren.

Nein, wäre es nicht. Da es Perl untypisch ist.
Du kannst mit for über jedes Element eines Array itterrieren und veränderungen an dem Skalar wirken sich auf das ursrpungsarray aus, also nutze es auch.
Nicht mehr aktiv. Bei Kontakt: ICQ: 404181669 E-Mail: perl@david-raab.de
<< |< 1 2 >| >> 13 Einträge, 2 Seiten



View all threads created 2007-08-29 14:02.