Schrift
[thread]8847[/thread]

2 Textdateien mergen: anfänger problem

Leser: 1


<< |< 1 2 >| >> 12 Einträge, 2 Seiten
Gast Gast
 2007-03-17 12:21
#75092 #75092
Hallo.
Ich bin in Sachen perl ein Anfänger.
Allerding möchte ich mir ein Script programmieren, dass mir den Inhalt einer kleinen Textdatei a automatisch ans Ende einer großen Textdatei b anfügt.

Da diese Arbeit jeden Tag fällig ist möchte ich das Script dann in den Windows Sceduler laden, damit das immer automtisch läuft.

Meine Frage an euch ist, ob mir jedand, mal den Quellcode für das kleine Programm aufschreiben kann bzw. ob mir jedemand verraten kann, welche perlfunktionen es dafür gibt.

Vielen Dank
PerlProfi
 2007-03-17 12:44
#75093 #75093
User since
2006-11-29
340 Artikel
BenutzerIn
[default_avatar]
Als erstes musst du die 1. Datei öffnen und
a) wenn sie klein ist ihren Inhalt speichern
b) wenn sie groß ist die 2. Datei direkt mit öffnen
und den Inhalt der ersten ans Ende der 2. schreiben.

Das geht mit open() und print().
Code: (dl )
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# Datei a öffnen
open(my$in, '<', $infile) or
die "Datei '$infile' konnte nicht geoeffnet werden: $!";

# ist Datei a zu groß um ihren Inhalt zu speichern,
# direkt Datei b öffnen
open(my$out, '>>', $outfile) or
die "Datei '$outfile' konnte nicht geoeffnet werden: $!";

# den Inhalt von Datei a an Datei b anhängen
while (<$in>)
{ print $out $_ }

# Datei b schließen
close($out);

# Datei a schließen
close($in);


edit: die() dazugepackt

MfG\n\n

<!--EDIT|PerlProfi|1174213573-->
bloonix
 2007-03-17 13:37
#75094 #75094
User since
2005-12-17
1615 Artikel
HausmeisterIn
[Homepage]
user image
@PerlProfi, ein die() nach open() wäre nicht schlecht.

Rückst du deinen Code immer so sinngemäß ein? Du musst aber wirklich
lange Codezeilen haben! :p
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.
PerlProfi
 2007-03-18 12:29
#75095 #75095
User since
2006-11-29
340 Artikel
BenutzerIn
[default_avatar]
Quote
Rückst du deinen Code immer so sinngemäß ein?

Klar, aber normalerweise mit Tab.
betterworld
 2007-03-18 17:38
#75096 #75096
User since
2003-08-21
2613 Artikel
ModeratorIn

user image
PerlProfi:
Vor while(<...>) fehlt ein local($_);

(Ist zwar in diesem Falle egal, aber sobald der Code mal in eine anonyme foreach-Schleife oder aehnliches eingebettet wird, gibt's sonst Aerger...)

Ach ja, und bei print und close sollte man auch noch die Fehler abfangen, denn die Festplatte (o. ä.) koennte ja voll sein.\n\n

<!--EDIT|betterworld|1174232724-->
BlueSky
 2007-03-23 15:49
#75097 #75097
User since
2007-03-23
1 Artikel
BenutzerIn
[default_avatar]
vielen dank erst mal für eure ausführlichen und hilfreichen antworten.

allerdings würde ich gern noch etwas ändern und ich bin mir nicht sicher, ob das geht.

In der großen Datei sollen nur die Daten der letzten 5 wochen drin sein.
Am Ende jedes Eintrags steht die Woche...zum Beispiel 200701 für die erste, 200702 für die zweite Woche 2007.
Wie könnte ich es organisieren, dass alle Einträge herausfallen die älter sind als die letzten 5 Wochen?

BlueSky
topeg
 2007-03-23 18:36
#75098 #75098
User since
2006-07-10
2611 Artikel
BenutzerIn

user image
Das ist Ungestestest und kann Schreibfehler enthalten. Aber so kann man es grundsätzlich machen.

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
#!/usr/bin/perl;
use strict;
use warnings;

my $infile='/pfad/zur/datei.in.txt';
my $outfile='/pfad/zur/datei.out.txt';
my $data='';

# Alte daten lesen
{
  local $/=undef;
  open(my $out_fh, '<', $outfile) or die "Konnte $outfile nicht öffnen ($!)\n";
  $data=<$out_fh>;
  close ($out_fh);
}

# die letzten 5 Datansätze herauslesen
# erst die Daten am Datum auteilen,
# dann die letzten 5 Einträge herausholen,
# wenn die Liste lang genug ist.
# Dann die Einträge wieder vereinen.
my @liste=split(/(?<=20\d{4})/s,$data);
@liste=@liste[-6..-1] if(@liste>5);
$data=join('',@liste);

# Neue Daten holen
# und anhängen.
{
  local $/=undef;
  open(my $in_fh, '<', $infile) or die "Konnte $infile nicht öffnen ($!)\n";
  $data.=<$in_fh>;
  close ($in_fh);
}

# Datensatz speichern
# und dabei die alten Daten überschreiben.
open(my $out_fh, '>', $outfile) or die "Konnte $outfile nicht öffnen ($!)\n";
print $out_fh $data;
close ($out_fh);
Dubu
 2007-03-26 16:13
#75099 #75099
User since
2003-08-04
2145 Artikel
ModeratorIn + EditorIn

user image
[quote=BlueSky,23.03.2007, 14:49]allerdings würde ich gern noch etwas ändern und ich bin mir nicht sicher, ob das geht.
[/quote]
Och, in Perl geht vieles.

Quote
In der großen Datei sollen nur die Daten der letzten 5 wochen drin sein.
Am Ende jedes Eintrags steht die Woche...zum Beispiel 200701 für die erste, 200702 für die zweite Woche 2007.
Wie könnte ich es organisieren, dass alle Einträge herausfallen die älter sind als die letzten 5 Wochen?

BlueSky

Das sollte es machen:
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
#!/usr/bin/perl
use strict;
use warnings;
use POSIX qw/strftime/; # fuer Monat und Jahr

my $maxalter = 5;               # maximales Alter in Wochen
my $gesamtdaten = 'alldata.dat';
my $neuedaten = 'newdata.dat';

my $backupsuffix = '.bak';      # Suffix fuer Backup der Daten
my $backupdaten = $gesamtdaten.$backupsuffix;
my $tmpsuffix = '.tmp';         # Suffix fuer temp. Datei
my $tmpdaten = $gesamtdaten.$tmpsuffix;

# Aktuelles Jahr und Woche ermitteln (Jahr vierstellig und Woche nach ISO 8601:1988)
my $jahrwoche = strftime ("%Y%V", localtime);

# Temporaere Datei fuer Ausgabe oeffnen
open my $tmpdaten_fh, '>', $tmpdaten
   or die "Kann $tmpdaten nicht zum Schreiben oeffnen: $!";

# Alte Daten kopieren
open my $gesamtdaten_fh, '<', $gesamtdaten
   or die "Kann $gesamtdaten nicht zum Lesen oeffnen: $!";

while (my $line = <$gesamtdaten_fh>) {
   # Jahr/Woche am Zeilenende?
   if ($line =~ /(\d{6})$/) {
       # Zeile ueberspringen, wenn zu alt
       next if $1 < $jahrwoche - $maxalter;
   } else {
       warn "Keine Datumsangabe am Ende von Zeile $. in $gesamtdaten, kopiere trotzdem!";
   }
   print $tmpdaten_fh $line;
}
close $gesamtdaten_fh or die "Kann $gesamtdaten nicht schliessen: $!";

# Neue Daten anhaengen
open my $neuedaten_fh, '<', $neuedaten
   or die "Kann $neuedaten nicht zum Lesen oeffnen: $!";
print $tmpdaten_fh (<$neuedaten_fh>);
close $neuedaten_fh or die "Kann $neuedaten nicht schliessen: $!";

# Das war's mit Schreiben
close $tmpdaten_fh or die "Kann $tmpdaten nicht schliessen: $!";

# Datei mit vorhandenen Daten umbenennen (als Backup)
rename $gesamtdaten, $backupdaten
   or die "Kann $gesamtdaten nicht in $backupdaten umbenennen: $!";

# Datei mit neuen Gesamtdaten in alten Namen umbenennen
rename $tmpdaten, $gesamtdaten
   or die "Kann $tmpdaten nicht in $gesamtdaten umbenennen: $!";

# Ende
exit 0;


Edit: code-Tags statt perl-Tags\n\n

<!--EDIT|Dubu|1174917139-->
renee
 2007-03-26 16:49
#75100 #75100
User since
2003-08-04
14371 Artikel
ModeratorIn
[Homepage] [default_avatar]
Benutzt bitte die [code]-Tags, wenn im Code $1 oder so vorkommt...

Ich versuche den Bug im [perl]-Tag zu fixen...
OTRS-Erweiterungen (http://feature-addons.de/)
Frankfurt Perlmongers (http://frankfurt.pm/)
--

Unterlagen OTRS-Workshop 2012: http://otrs.perl-services.de/workshop.html
Perl-Entwicklung: http://perl-services.de/
betterworld
 2007-03-26 17:50
#75101 #75101
User since
2003-08-21
2613 Artikel
ModeratorIn

user image
[quote=renee,26.03.2007, 14:49]Benutzt bitte die [code]-Tags, wenn im Code $1 oder so vorkommt...[/quote]
Ich wollte gerade noch "\n" ergaenzen, aber damit scheinen die perl-Tags inzwischen keine Probleme mehr zu haben. Danke an den unbekannten Fixer..
<< |< 1 2 >| >> 12 Einträge, 2 Seiten



View all threads created 2007-03-17 12:21.