Schrift
[thread]13181[/thread]

Bestimmte Zeilen und Spalten aus txt. Datei in eine andere txt.-Datei schreiben

Leser: 5


<< |< 1 2 >| >> 15 Einträge, 2 Seiten
MrDizzle
 2009-02-25 16:35
#119135 #119135
User since
2009-02-25
2 Artikel
BenutzerIn
[default_avatar]
Hallo Perl-Programmierer

ich habe ein großes Problem und zwar:

Mein Simulationsprogramm gibt mir eine Datei mit 8 Spalten (separiert durch Tab) und 100000 Zeilen.
Ich möchte nur einen Teil in ein txt.-File schreiben. Und zwar die letzten 100 Zeilen und die 3 bis 6 Spalte, die Werte sollen statt durch tab mit einem Komma getrennt sein. Es handelt sich hier generell nur um Zahlenwerte.
Ich habe es bis jetzt nur geschafft mir die letzten 100 Zeilen raus zu schreiben, aber mit den Spalten auswählen und zusammenfügen habe ich nicht gepackt.
Wenn ihr helfen könntet, wäre es das echt cool. Bin erst seit 2 Tagen an Perl dran, daher ein blutiger Anfänger.
Danke schon mal im Voraus.


Spalte1 Spalte2 Spalte3 Spalte4 Spalte5 Spalte6 Spalte7
Zeile1
Zeile2
..
.
Zeile100000
Gast Gast
 2009-02-25 16:55
#119137 #119137
Sorry,
hier noch das ,was ich bis jetzt fabrizieren konnte:

[perl]
$Kugelanzahl=50;
$Zeit=2;
$Zeitabstand=0.001;
$Zeitschritte=$Zeit/$Zeitabstand;
open(DATEI, "<VelocityPlot.dem");
open(SESAM, ">test.inp");

while (<DATEI>)
# {
# @line = split / /, $_;
#}
{if ($. > $Kugelanzahl*$Zeitschritte-$Kugelanzahl)

{ print SESAM "a,b,c,",$_ }}

#print $., " Zeilen gelesen";
close(DATEI);
close(SESAM);

a,b,c soll er hier nur vor jede geschriebene Zeile setzen.
#Kein Kommentar
 2009-02-25 17:35
#119138 #119138
User since
2007-06-09
575 Artikel
HausmeisterIn
[default_avatar]
dabei können dir die funktionen split und join helfen.

mit split trennst du einen string in teile auf:
Code: (dl )
my @parts = split /\t/, $line;


und mit join kannst du sie wieder zusammenfügen:
Code: (dl )
my $new_line = join ',', @parts;


daraus kannst du folgendes basteln:
Code: (dl )
1
2
3
4
foreach my $line (@lines){
my @parts = split /\t/, $line; # splittet alle tabulatorzeichen
my $new_line = join ',', $parts[2], $parts[3], $parts[4], $parts[5]; # fügt alle teile mit einem komma wieder zusammen
}


die datei einlesen und die daten in eine neue datei zu schreiben, das hast du ja schon selber hinbekommen.

wenn du noch fragen hast meld dich ruhig
Gerade weil wir alle in einem Boot sitzen, sollten wir froh sein, dass nicht alle auf unserer Seite sind
murphy
 2009-02-25 17:55
#119140 #119140
User since
2004-07-19
1776 Artikel
HausmeisterIn
[Homepage]
user image
1. Du solltest auf jeden Fall strict und in aller Regel auch warnings benutzen. Siehe auch Wiki:UseStrict.

2. -f split ist das richtige Werkzeug, um eine Zeichenkette in mehrere Felder zu zerlegen, -f join fuegt mehrere Zeicheketten wieder mit Trennzeichen zusammen.

3. Eine Kombination der Unix-Kommandozeilentools tail und cut koennte die gewuenschte Aufgabe wohl auch erledigen, aber wenn Du vielleicht noch mehr machen willst, ist Perl natuerlich besser :-)
When C++ is your hammer, every problem looks like your thumb.
MrDizzle
 2009-02-25 18:49
#119143 #119143
User since
2009-02-25
2 Artikel
BenutzerIn
[default_avatar]
Ahh
Sorry aber wie soll ich foreach und if miteinander verknüpfen, kommt das WHILE raus?
Sind die allgemeinen Variablen $. und $_ zu ersetzen.....
Tut mir leid aber ic hahbe vorher noch keine Programmiersprache angerührt
Großes Dank schon mal an euch!!
hlubenow
 2009-02-25 20:01
#119151 #119151
User since
2009-02-22
875 Artikel
BenutzerIn
[default_avatar]
Hi,

meinst Du das so (?):
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
#!/usr/bin/perl

use warnings;
use strict;

my $infile = "VelocityPlot.dem";
my $outfile = "test.inp";

open(FH, "<$infile");
my @a = <FH>;
close(FH);

my $alen = @a;
my $i;
my @b;

open(FH, ">$outfile");

for($i = $alen - 101; $i < $alen; $i++)
{
    @b = split("\t", $a[$i]);
    my $d = "";
    for(my $u = 3; $u <= 6; $u++)
    {
        $d = $d . $b[$u - 1];
        if($u < 6)
        {
            $d = $d . ",";
        }
    }
    print(FH "$d\n");
}

close(FH);

Gruß
leo11
 2009-02-25 21:32
#119155 #119155
User since
2008-08-14
250 Artikel
BenutzerIn
[default_avatar]
hlubenow+2009-02-25 19:01:42--
open(FH, "<$infile");
my @a = <FH>;
close(FH);


Das bedeutet die gesamte Datei wird in einem Array gespeichert, was mehr Speicher benötigt. Ich würde das eher mit Tie::File lösen. Ich hab damit vor kurzem gute Erfahrungen gemacht. In der Doku steht auch, dass dieses Modul für sehr große Dateien geeignet ist. Hier mein Vorschlag:

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
#!/usr/bin/perl 
use strict;
use warnings;
use Tie::File;
use Data::Dumper;

my $datei = q(file.txt);

use Tie::File;

tie my @array, 'Tie::File', $datei or die $!; # @array mit Tie::File an $datei binden

# jetzt etwas mit @array anstellen 
my $anzahl_zeilen = @array;
my $anzahl_zu_kop_zeilen = q(3);
my @spalten;

for ( my $i = ($anzahl_zeilen - $anzahl_zu_kop_zeilen); $i < $anzahl_zeilen; $i++){ 
    @spalten = split("\t", $array[$i]);
    print join(",",$spalten[2] .. $spalten[5]), "\n";
}

#print Dumper \@spalten;
untie @array;  #und wenn's erledigt ist untie
havi
 2009-02-25 23:47
#119158 #119158
User since
2003-08-04
2036 Artikel
BenutzerIn
[Homepage]
user image
MrDizzle+2009-02-25 15:35:33--
Hallo Perl-Programmierer

ich habe ein großes Problem und zwar:

Mein Simulationsprogramm gibt mir eine Datei mit 8 Spalten (separiert durch Tab) und 100000 Zeilen.
Ich möchte nur einen Teil in ein txt.-File schreiben. Und zwar die letzten 100 Zeilen und die 3 bis 6 Spalte, die Werte sollen statt durch tab mit einem Komma getrennt sein. Es handelt sich hier generell nur um Zahlenwerte.
Ich habe es bis jetzt nur geschafft mir die letzten 100 Zeilen raus zu schreiben, aber mit den Spalten auswählen und zusammenfügen habe ich nicht gepackt.
Wenn ihr helfen könntet, wäre es das echt cool. Bin erst seit 2 Tagen an Perl dran, daher ein blutiger Anfänger.
Danke schon mal im Voraus.


Spalte1 Spalte2 Spalte3 Spalte4 Spalte5 Spalte6 Spalte7
Zeile1
Zeile2
..
.
Zeile100000


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
#!/usr/bin/perl

use warnings;
use strict;

# Zeilenanzahl ermitteln
open(my $fhZl, "<Test.txt") or die $!;
my $cnt = 0;
while(my $z = <$fhZl>) {
$cnt = $.;
} # while
close($fhZl) or die $!;

# Die letzten 100...
my $zl = 0;
$zl = $cnt - 100;

# Tab getrennt einlesen, Komma getrennt rausschreiben
# und zwar die letzten 100 Zeilen
open(my $fhEin, "<Test.txt") or die $!;
open(my $fhAus, ">Ausgabe.txt") or die $!;

while(my $zeile = <$fhEin>) {

if ($. > $zl) { # $. enthaelt die aktuelle Zeilennummer
my @array = ();
@array = split(/\t/, $zeile);
print $fhAus join(",", @array[2..5])."\n";
} # if

} # while

close($fhEin) or die $!;
close($fhAus) or die $!;

print "Fertig.\n";

1;


funkt ;)
murphy
 2009-02-26 01:11
#119160 #119160
User since
2004-07-19
1776 Artikel
HausmeisterIn
[Homepage]
user image
@leo11: Ich bezweifle ja, dass der Ausdruck $spalten[2] .. $spalten[5] wirklich das tut, was hier gewuenscht ist.

Mein Vorschlag fuer eine kompakte Loesung als Filter waere folgender:
Code (perl): (dl )
1
2
3
4
5
6
7
8
9
10
11
12
13
14
use strict;
use warnings;

use constant {
    COUNT => 10,
    SELECT => [ 2 .. 5 ]
};

use Tie::File;

tie my @lines, 'Tie::File', \*STDIN;

print join(',', (split /\s+/)[@{(SELECT)}]), "\n"
    foreach (@lines[@lines - COUNT .. $#lines]);
When C++ is your hammer, every problem looks like your thumb.
Gast Gast
 2009-02-26 02:22
#119162 #119162
Code: (dl )
perl -anle 'BEGIN{$"=q{,}} $. > 99990 && print "@F[2..5]"' infile

oder kürzer:
Code: (dl )
perl -anle '$. > 99990 && print join ",", @F[2..5]' infile
<< |< 1 2 >| >> 15 Einträge, 2 Seiten



View all threads created 2009-02-25 16:35.