Schrift
[thread]8949[/thread]

Zeichenketten aus einer Datei lesen ->: und in einer anderen Datei zufügen

Leser: 1


<< |< 1 2 >| >> 14 Einträge, 2 Seiten
SimplyFred
 2007-04-26 17:10
#76262 #76262
User since
2006-12-16
25 Artikel
BenutzerIn
[default_avatar]
Hallo,

ich habe eine txt-Datei, in der stehen Zeichen drinne, die ich in eine "andere Datei" gezielt an einen Ort bringen möchte

Inhalt:"txt-Datei"
3333;geht ab hier in andere Datei
3334;geht ab hier in andere Datei


Inhalt:"andere Datei"
1111;Test1111;netfe;aaaaa;ccccc;ggggg;;;;xyxyxyxyx;net;0                                                                                                                                                                                                                                                          
1112;Tester1112;netfe;aaaaa;bbbb;hhhh;hhhh;uu;;xyxyxyxyx;net;0                                                                                                                                                                                                                                                    
1113;gerd;Gerd;cccc;cccc;rrr;ff;;;xyxyxyxyx;net;0                                                                                                                                                                                                                                                                
2221;peter;Peter;ffff;;;;;;xyxyxyxyx;net;0                                                                                                                                                                                                                                                                              
2222;holger;Holger;ffff;;;;;;xyxyxyxyx;net;0                                                                                                                                                                                                                                                                        
2226;Willfried;Peter;ffff;;;;;;xyxyxyxyx;net;0                                                                                                                                                                                                                                                                            
3333;Hoss;Guenter;ffff;Aachen;hhh;gg;fff;;xyxyxyxyx;net;0                                                                                                                                                                                                                                          
3334;Mueller;Michael;ffff;aachen;hhh;;;;xyxyxyxyx;net;2
                                                       
Die letzten beiden Zeilen der Datei sollen dann so aussehen, die anderen bleiben unverändert:
3333;Hoss;Guenter;ffff;Aachen;hhh;gg;fff;;xyxyxyxyx;net;2;geht ab hier in andere Datei
3334;Mueller;Michael;ffff;aachen;hhh;;;;xyxyxyxyx;net;2;geht ab hier in andere Datei
                                                       
Im Klartext:
Alles was nach 3333; und 3334; kommt soll ans Ende der Zeile angefügt werden                                                        
                                                       
Wie kann man sowas relativ einfach realisieren ?
Bin um Tipps sehr dankbar !
murphy
 2007-04-26 19:08
#76263 #76263
User since
2004-07-19
1776 Artikel
HausmeisterIn
[Homepage]
user image
Was Du da realisieren möchtest nennt man bei Datenbanken auch eine relationale Join-Operation. Ich denke daher, dass es sich lohnen würde, die Daten in eine SQL-Datenbank zu übertragen und über die CPAN:DBI-Schnittstelle mit SQL-Befehlen darauf zuzugreifen.

Wenn kein Datenbankserver zur Verfügung steht und / oder kein Zugriff von mehreren Rechnern auf die Datensätze nötig ist, würde ich eine Dateidatenbank wie SQLite (Perlanbindung: CPAN:DBD::SQLite) empfehlen.

Falls die Datenmenge sehr klein ist und die Operation nur einmalig durchgeführt werden muss, könnte man, statt eine echte Datenbank einzusetzen, vielleicht auf CPAN:DBD::CSV zurückgreifen, um die CSV-Dateien mittels SQL anzusprechen.

edit: Nur der Vollständigkeit halber: Der SQL-Befehl, den man hier bräuchte, sähe etwa so aus
SELECT * FROM Table0 LEFT OUTER JOIN Table1 ON Table0.column0 = Table1.column1;.\n\n

<!--EDIT|murphy|1177600474-->
When C++ is your hammer, every problem looks like your thumb.
PerlProfi
 2007-04-26 19:12
#76264 #76264
User since
2006-11-29
340 Artikel
BenutzerIn
[default_avatar]
Du könntest auch die Daten alle einlesen, bearbeiten und wieder rausschreiben, ohne Modul.
Falls die Reihenfolge der Zeilen dabei verändert werden darf, kannst du Hashes benutzen:
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
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
#!/usr/bin/perl
use strict;
use warnings 'all';

# initialize filenames
my $erste_datei = 'test1.txt';
my $andere_datei = 'test2.txt';

# read files
my $data_to_append = &datei_lesen($erste_datei);
my $full_data = &datei_lesen($andere_datei);

# append data
foreach my$key (keys %{$data_to_append})
{
# check whether we can append the data
next if !exists($full_data->{$key});

# append data
push(@{$full_data->{$key}}, @{$data_to_append->{$key}});
}

# output
&datei_schreiben($full_data, $andere_datei);

# NAME: datei_schreiben()
# USE: Datei anhand des musters in eine Datei schreiben
# PARAMETERS: 1. Data
# 2. Filename
# RETURNS: void
sub datei_schreiben($$)
{
# pick parameters
my($data, $file) = @_;

# open file
open(my$fhOUT, '>', $file)
or die "open failed: $!";

# iterate through the data
foreach my$key (keys %{$data})
{
# create line
my $line = $key . ';' . join(';', @{$data->{$key}});

# write out line
print $fhOUT "$line\n";
}

# close file
close($fhOUT)
or die "close failed: $!";
} # datei_schreiben

# NAME: datei_lesen()
# USE: Datei anhand des musters in eine komplexe Datenstruktur einlesen.
# PARAMETERS: Filename
# RETURNS: Hash reference
sub datei_lesen($)
{
# pick parameters
my($file) = @_;

# open file
open(my$fhIN, '<', $file)
or die "open failed: $!";

# read data
my %data;
while (my$line=<$fhIN>)
{
chomp($line);

# split line
my @tracts = split(';', $line);

# key equals the first tract
my $key = shift @tracts;
my $val = [@tracts];

# push data
$data{$key} = $val;
}

# close file
close($fhIN);

# return data reference
return \%data;
} # datei_lesen

Darf die Reihenfolge nicht verändert werden, könntest du die Daten in Arrays sammeln, dazu müsstest du in obigem code nur die Zugriffe auf die Daten abändern.

MfG\n\n

<!--EDIT|PerlProfi|1177600573-->
Gast Gast
 2007-04-26 21:26
#76265 #76265
Erst einmal:
Ihr seid ja echt der Wahnsinn - das gibt es doch gar nicht sowas ... wie kann man nur soviel Code direkt aus dem Aermel schuetteln. Auch speziellen Dank an "murphy".
Ist schon soweit richtig erkannt, dass da eine SQL im Hintergrund werkelt, aber die Datenbank soll nur einmal eine Datei einlesen, womit ich wohl die Dateien tatsächlich verändern muss.
JA, die Reihenfolge ist eigentlich egal, Hauptsache am Ende der entsprechenden Zeile werden die Einträge richtig ergänzt.

Eins im Code ist mir nicht klar - was bedeutet ?
# NAME: datei_schreiben()
# USE: Datei anhand des musters in eine Datei schreiben
# PARAMETERS: 1. Data
# 2. Filename
# RETURNS: void


Da werd ich mich mal ranmachen und rumprobieren, erstmal VIELEN VIELEN Dank - werde mich melden bei auftretenden Problemen

Ich hoffe, ich bekomme das einigermassen hin.
Eins noch: In meinem Beispiel stehen fälschlicherweise ";" als Trenner, tatsächlich sind es aber "#"
Tut dem Ganzen aber hoffe ich keinen Abbruch

Vielen Dank nochmal und ich melde mich !
Gruss
SimplyFred
PerlProfi
 2007-04-27 00:58
#76266 #76266
User since
2006-11-29
340 Artikel
BenutzerIn
[default_avatar]
Das sind nur Kommentare, in dieser Form kommentiere ich meine Funktionen immer, dass hab ich mir irgendwann so angewöhnt.
Sieht ein bisschen komisch aus, wegen den Tabstops, macht hoffentlich nichts.

Wenn die Trenner andere sind, musst du nur an 2 Stellen ein ';' in ein '#' umändern.
1. in der Funktion datei_schreiben(), nach dem Kommentar # create line beide ';' in '#'
2. in der Funktion datei_lesen(), nach dem Kommentar # split line das ';' in '#'

MfG
SimplyFred
 2007-04-27 15:23
#76267 #76267
User since
2006-12-16
25 Artikel
BenutzerIn
[default_avatar]
Hallo,

ja danke, das hatte ich gestern Abend schon gemacht und auch einen kurzen Test konnte ich machen - EINWANDFREI !!!!

In meiner Datei, in die das Ergebnis reingeschrieben wird sind nach dem "....xyxyxyxyx#net#2" noch ein Haufen Leerzeichen, keine Ahnung wo die herkommen, aber die Datei wird leider schon so erzeugt.
Jetzt kommt natuerlich mein Eintrag erst nach die ominösen Leerzeichen.
Das ist nur ein Schönheitsfehler, ich weiss, aber wegen der Übersichtlichkeit wäre es schön, wenn das Ergebnis DIREKT nach der "2" auftauchen würde.

Ungefähr so: "....xyxyxyxyx#net#2#eingelesener Text"

Ich weiss, so sollte es ja auch sein, man wusste ja nicht, dass da noch viele Leerzeichen sind.

ABER SUPER !!! Jetzt kann ich das Ganze noch ein wenig mit Log-Datei etc. erweitern, das schaffe ich irgendwie schon.

Jungs ihr seid grossartig !
murphy
 2007-04-27 16:33
#76268 #76268
User since
2004-07-19
1776 Artikel
HausmeisterIn
[Homepage]
user image
Die Leerzeichen am Ende der Zeile kannst Du vermutlich ganz leicht mit einem regulären Ausdruck entfernen: Zum Beispiel könntest Du in PerlProfis Skript in der Subroutine datei_lesen die Zeile chomp($line); ("wirf am Ende von $line alles weg, was wie ein Zeilenumbruch aussieht") durch $line =~ s/\s*$//; ("wirf am Ende von $line alles weg, was Whitespace ist") ersetzen.

Am Rande bemerkt: Auch wenn PerlProfis Skript natürlich für einfach formatierte Daten funktioniert, würde ich bei CSV-Dateien generell lieber mit einem Modul wie CPAN:Text::CSV, CPAN:Text::CSV_XS oder CPAN:DBD::CSV arbeiten, weil man dann keine bösen Überraschungen erlebt, für den Fall, dass in der CSV-Datei doch mal Quotes oder Escapesequenzen vorkommen...\n\n

<!--EDIT|murphy|1177677457-->
When C++ is your hammer, every problem looks like your thumb.
PerlProfi
 2007-04-27 16:38
#76269 #76269
User since
2006-11-29
340 Artikel
BenutzerIn
[default_avatar]
edit: murphy war schneller und besser

Allerdings müsstest du, wenn du das Skript an der Stelle mit dem regulären Ausdruck veränderst noch den m-modifier dranschieben, ansonsten kommt das \n nicht mit weg.\n\n

<!--EDIT|PerlProfi|1177677681-->
murphy
 2007-04-27 16:58
#76270 #76270
User since
2004-07-19
1776 Artikel
HausmeisterIn
[Homepage]
user image
Nein, der m-Schalter für den regulären Ausdruck ist in diesem Fall überflüssig.

Es ist nämlich so: Das Muster \s passt stets auch auf Zeilenumbrüche. Die Verwendung des m-Schalters führt lediglich dazu, dass ^ und $ nicht mehr nur auf den Anfang bzw. das Ende der gesamten Zeichenkette, sondern auch auf die Position nach bzw. vor einem Zeilenumbruch passen.

Es ergibt sich also folgendes Verhalten:

* $line =~ s/\s*$//; löscht aus $line beliebig viele Whitespaces, inklusive Zeilenumbrüchen, die am Ende der Zeichenkette stehen.

* $line =~ s/\s*$//m; löscht aus $line beliebig viele Whitespaces, die am Ende der Zeichenkette oder[1] vor dem ersten Zeilenumbruch stehen.

Daher ist es in unserem Anwendungsfall egal, ob man den m-Schalter angibt, oder nicht. Eventuell ist es ohne den Schalter um ein paar Nanosekunden schneller ;-)


[1] hier ist ein exklusives "oder" gemeint.
When C++ is your hammer, every problem looks like your thumb.
PerlProfi
 2007-04-27 19:23
#76271 #76271
User since
2006-11-29
340 Artikel
BenutzerIn
[default_avatar]
jo stimmt hast recht, irgendwo muss ich mich da vertan haben.
<< |< 1 2 >| >> 14 Einträge, 2 Seiten



View all threads created 2007-04-26 17:10.