[Perl] Datei mit Tabulator einlesen


chill0r55555

Mitglied
Guten Abend an Alle,

ich steh grad vor einem für mich eher großem Problem. Ich habe eine Datei (datei1.txt) dort stehen Werte mit einem Tabulator getrennt drinnen. Also so:

datei.txt
Code:
test     123
bla1     478
bla2     720


Dann hab ich eine 2te Datei (datei2.txt). Diese sieht so aus:

Code:
test     test.htm
bla1     bla1.htm
bla2     bla2.htm
Die Werte sind auch hier mit einem Tabulator getrennt.

Ich möchte nun realisieren, dass ich Datei1 einlese und in ein Array speichere. Es kommt mir hier auf die erste Spalte an.
Dann möchte ich in der 2ten Datei nach den Werten (test,bla1,bla2) in Datei2 suchen.
Wenn ich nun einen Treffer habe, dann soll der dazugehörige Zahlenwert aus Datei1 ans Ende der Zeile in Datei 2 geschrieben werden.
Als Beispiel:

Datei1
Code:
test[TABULATOR]123

Nun suche ich nach "test" in Datei 2. Ich erhalte einen Treffer und schreibe den Wert von test (123) ans Ende der Trefferzeile in Datei 2.

Datei2
Code:
test[TABULATOR]test.htm[TABULATOR]123
bla1[TABULATOR]bla1.htm
bla2[TABULATOR]bla2.htm

Leider klappt das einlesen mit meiner Methode auch noch nicht so ganz :(
Es werden mir mit diesem Code immer nur die letze Zeile der Datei 1 ausgegeben:

Code:
open (DATEI, "<datei1.txt") || die "Datei wurde nicht gefunden\n"; # einlesen der datei
while(<DATEI>) #während des einlesens....
{ 
@temp = split (/\t/, $_ ); #am tab trennen der aktuellen zeile
}
close (DATEI); # datei schließen

#ausgabe...

for ($i=0;$i<@temp;$i++){
print "$temp[$i]\n";
}

Ich hoffe das war nun verständlich ausgedrückt und mir kann einer sagen wie ich hier vorgehen könnte. Ich bedanke mich schonmal im vorraus.

mfg
 

Enumerator

Mitglied Kamel
Abend!
Wie wär's damit?

Code:
#!/usr/bin/perl
#
# strict sieht einfach bessa aus ...
# ---

  use strict;

# ---
# allerdings müssen wir jetzt alles "deklarieren"...
# ---

  my @tempEinz = (); 	my $datei;
  my @tempZwei = (); 	my $count = 0;

# ---
# ok, lass uns mal die zwei dateien einlesen. leider müssen wir die arrayglättung umgehen.
# ---

  open ($datei, '<', 'datei1.txt') or die "Datei1 wurde nicht gefunden\n";
  while(<$datei>)
  {
	chomp;
	@{$tempEinz[$count++]} = split("\t", $_);
  }
  close $datei;

  $count = 0;

  open ($datei, '<', 'datei2.txt') or die "Datei2 wurde nicht gefunden\n";
  while(<$datei>)
  {
	chomp;
	@{$tempZwei[$count++]} = split("\t", $_);
  }
  close $datei;

# ---
# jetzt überprüfen wir die gemeinsamkeiten und schreiben auch gleich die dritte datei.
# natürlich kann das auch wieder datei 2 sein, aber erstmal testen ;-)
# ---

  open ($datei, '>', 'datei3.txt') or die "Datei 3 blabla\n";

  for(my $i=0; $i <= $#tempZwei; ++$i)
  {
	print $datei join "\t", @{$tempZwei[$i]};

	for(my $j=0; $j <= $#tempEinz; ++$j)
	{
		if(@{$tempEinz[$j]}->[0] eq @{$tempZwei[$i]}->[0])
		{
			print $datei ("\t".@{$tempEinz[$j]}->[1]);
		}
	}

	print $datei "\n";
  }

  close $datei;

# ---
# soo, jetzt geben wir noch eine schöne EINZ zurück und wenn ich mich zu so später stunde nicht
# total vertippt habe und dein prob richtig verstanden ... hast du jetzt keins mehr
# ---

  1;
__END__

Mfg
Enum
 
Zuletzt bearbeitet:

chill0r55555

Mitglied
Hallo,
ich danke dir das du so schnell geantwortet hast.
Leider funktioniert das ganze noch nicht so ganz.

Hier sind mal die Origininal Dateien (Anhang). Prinzip ist das gleiche wie oben beschriebn, nur dass ich dort Dummy Daten benutzt habe. Ich kenn mich leider noch nicht so aus mit Perl aber ich denke der Fehler liegt auch an dem komemntar in datei2.txt:confused:


mfg
 

Anhänge

  • datei1.txt
    62 Bytes · Aufrufe: 61
  • datei2.txt
    638 Bytes · Aufrufe: 54

Enumerator

Mitglied Kamel
Also, das ist natürlich ein Problem. Du kannst die Kommentarzeilen mit einem eindeutigen String einleiten (wie z.B. '--', das scheint ja so zu sein...) und mit Requlären ausdrücken abfangen und als komplette Zeile speichern. Allerdings musst Du dann wiederum bei der Ausgabe den Typ der Zeile (Array/Skalar) abfragen und enstprechend handeln...
Code:
#!/usr/bin/perl
#
# strict sieht einfach bessa aus ...
# ---

  use strict;

# ---
# allerdings müssen wir jetzt alles "deklarieren"...
# ---

  my @tempEinz = (); 	my $datei;
  my @tempZwei = (); 	my $count = 0;

# ---
# damit werden kommentarzeilen EINDEUTIG eingeleitet:
# ---

  my $kommentar = '--';

# ---
# ok, lass uns mal die zwei dateien einlesen. leider müssen wir die arrayglättung umgehen.
# ---

  open ($datei, '<', 'datei1.txt') or die "Datei1 wurde nicht gefunden\n";
  while(<$datei>)
  {
	chomp;

	if($_=~ /$kommentar.*/) 
	{
		$tempEinz[$count++] = $_;
	}
	else
	{
		@{$tempEinz[$count++]} = split("\t", $_);
	}
  }
  close $datei;

  $count = 0;

  open ($datei, '<', 'datei2.txt') or die "Datei2 wurde nicht gefunden\n";
  while(<$datei>)
  {
	chomp;

	if($_=~ /$kommentar.*/)
	{
		$tempZwei[$count++] = $_;
	}
	else
	{
		@{$tempZwei[$count++]} = split("\t", $_);
	}
  }
  close $datei;

# ---
# jetzt überprüfen wir die gemeinsamkeiten und schreiben auch gleich die dritte datei.
# natürlich kann das auch wieder datei 2 sein, aber erstmal testen ;-)
# ---

  open ($datei, '>', 'datei3.txt') or die "Datei 3 blabla\n";

  for(my $i=0; $i <= $#tempZwei; ++$i)
  {
	if(ref($tempZwei[$i]))
	{
		print $datei (join "\t", @{$tempZwei[$i]});

		for(my $j=0; $j <= $#tempEinz; ++$j)
		{
			if(ref($tempEinz[$j]))
			{
				if(@{$tempEinz[$j]}->[0] eq @{$tempZwei[$i]}->[0])
				{
					print $datei ("\t".@{$tempEinz[$j]}->[1]);
				}
			}
		}
	}
	else { print $datei $tempZwei[$i]; } print $datei "\n" unless $i == $#tempZwei;
  }

  close $datei;

# ---
# so...
# ---

  1;
__END__

Mfg
Enum
 
Zuletzt bearbeitet:

chill0r55555

Mitglied
Wow :eek:
Ich danke dir vielmals! Das ist genu was ich gebraucht habe. Werd das ganze jetz noch schön Zeile für Zeile durchgehn um zu verstehn was genau gemacht wird. Ich will ja auch was lernen.

Danke nochmals:)
 

chill0r55555

Mitglied
Hallo,

ich bin bei dem nun fertigen Skript auf ein Problem gestoßen.
Undzwar prüft er ja hier ob die Vorkommen in Array1 und Array2 an der Stelle 0 gleich sind.
Sollte dies der fall sein, dann hängt er mir den Wert aus Datei1 in Datei2 hinten an mit ein davor eingefügten Tabulator.

Code:
if(@{$tempArray1[$j]}->[0] eq @{$tempArray2[$i]}->[0])
{
print $datei ("\t".@{$tempArray1[$j]}->[1]);
}

Wenn ich nun aber den Wert in Datei1 ändere, dann wird mir der neue Wert an den alten angehängt mit vorrausgegehndem Tabulator in Datei2. Ich habe probiert die den alten Wert in Datei2 zu überschreiben, bin hier aber leider gescheitert:

Code:
if(@{$tempArray1[$j]}->[0] eq @{$tempArray2[$i]}->[0])
{
print $datei (@{$tempArray1[$j]}->[1]);
}

Was mache ich hier flasch?

MfG
 

Enumerator

Mitglied Kamel
Moin!

Wenn ich Dich richtig verstanden habe, löst das hier das Problem. Allerdings werden nun zwar alte Werte ersetzt, doch fehlt der alte Wert in Datei1, wird er auch in Datei2/3 beseitigt.
Code:
print $datei @{$tempZwei[$i]}->[0] ."\t". @{$tempZwei[$i]}->[1];
Das könnte man natülich auch vermeiden, doch ich glaube so macht es mehr Sinn - oder?

Gruß
Enum

PS: Die zu ändernde Zeile ist diese:
Code:
print $datei (join "\t", @{$tempZwei[$i]});
Beachte bitte, dass Du evtl. Fehler bekommst, sollte die Zeile in Datei2 vorher nicht in dem von Dir oben definierten Format ([WERT][TAB][WERT]....) vorliegen. In diesem Fall kann es passieren, dass
Code:
@{$tempZwei[$i]}->[1]
nicht existiert...
 
Zuletzt bearbeitet: