mrks: Verschachtelte for-each Schleifen mit s///

Hallo allerseits!

Der folgende Code sollte: einen Stringvergleich zwischen Werten aus 2 Arrays durchführen. Wenn der match erfolgreich ist, dann sollte ein Teilstring der 2. Arrayvariable durch einen bestimmten Text ersetzt werden.

Dazu habe ich 2 verschachtelte foreach-Schleifen verwendet:

  
foreach (@input_datei)  
{  
	$var1 =$_;  
	  
         foreach (@input_datei_2){  
			$_=~s#\$var1#<a href="$1">$1</a>#;  
			}  
			  
}  
  
print @inputdatei;

Kann mir bitte jemand sagen warum es nicht funktioniert? Ich vermute stark, dass mit s/// etwas nicht in Ordnung ist. Optional habe ich auch mit s#\Q$var1\E#TEST# gearbeitet. Brachte auch nichts. Darf zwischen den ersten beiden // keine Variable stehen?

Eine andere Vermutung: der Wert von $var1 geht in der 2. Schleife irgendwie verloren. Bin jedenfalls ratlos und blind für eine Lösung. Danke im Voraus.

  1. [code lang=perl]
    foreach (@input_datei)
    {
    $var1 =$_;

    foreach (@input_datei_2){
    $_=~s#$var1#<a href="$1">$1</a>#;

    mit $var suchst du nach nach dem Literal $var.
    du suchst \Q$var
    $1 referenziert den Inhalt der ersten Klammer.
    Ich finde bei dir keine Klammer.
    Im übrigen ist in $var am Ende ein Linefeed \n enthalten.

    mfg Beat

    --
    ><o(((°>           ><o(((°>
       <°)))o><                     ><o(((°>o
    Der Valigator leibt diese Fische
    1. »» ~~~perl

      »» foreach (@input_datei)
      »» {
      »» $var1 =$;
      »»
      »»          foreach (@input_datei_2){
      »» $
      =~s#$var1#<a href="$1">$1</a>#;

      mit $var suchst du nach nach dem Literal $var.
      du suchst \Q$var
      $1 referenziert den Inhalt der ersten Klammer.
      Ich finde bei dir keine Klammer.
      Im übrigen ist in $var am Ende ein Linefeed \n enthalten.

      mfg Beat

      Danke für die schnelle Antwort!

      Dass ich mit $1 eine klammer referenziere ist mir klar. Der Code hätte heißen sollen:

      $_=~s#($var1)#<a href="$1">$1</a>#;

      Da war ich etwas schlampig - sorry.

      Ist \Q also die Lösung? Leider erziele ich damit auch nicht die gewünschten Ergebnisse.
      Hier der ganze Code:

      [code lang=perl]
      #!usr/bin/perl
      use utf8;
      use warnings;

      open INPUTDATEI, "<", "e:\-----.txt" || die "Datei nicht geoeffnet, weil: $!";
      open ZWEITEINPUTDATEI, "<", "e:\-------.txt" || die "Datei nicht geoeffnet, weil: $!";
      open OUTPUTDATEI, "+>", "e:\--------.txt" || die "Datei nicht geoeffnet, weil: $!";

      @inputdatei = <INPUTDATEI>;
      @zweiteinputdatei = <ZWEITEINPUTDATEI>;

      foreach (@zweiteinputdatei){
      $var1 =$;
      foreach (@inputdatei)
      {
      $
      =~s#\Q$var1#TEST#;
      print OUTPUTDATEI $_;
      }
      }

        
      Ziel wäre die Ersetzung der Zeilen aus der Inputdatei durch dieses TEST wenn $var1 die jeweilige Zeile matcht. Der modifizierte Text soll also gleich in die Outputdatei geschrieben werden.  
        
      Mit dem Line-Feed hast Du Recht. Das könnte man aber mit chomp ($var1) wohl wegbekommen. Bin mir aber sicher, dass nicht dieses Line-Feed das Problem ist.  
        
      mfg mrks  
        
        
        
        
        
      
      
      1. Schönen guten Abend,

        Erstmal: Benutze use strict;.
        Was genau funktioniert denn nicht bzw. was funktioniert bei dir im moment? Matcht $var1 die Zeile nicht? Findet keine Ersetzung statt?

        print OUTPUTDATEI $_;

        Du weisst, dass du in die OUTPUTDATEI den Dateiinhalt der INPUTDATEI in der Menge der Zeilen der Datei schreibst?

        --
        suit: JavaScript ist nur das Schirmchen am Eisbecher - der Eisbecher muss auch ohne dem Schirmchen lecker sein.
        Selfcode: sh:( fo:) ch:| rl:( br:< n4:( ie:{ mo:| va:) de:> zu:) fl:( ss:) ls:> js:)
        1. Schönen guten Abend,

          Erstmal: Benutze use strict;.
          Was genau funktioniert denn nicht bzw. was funktioniert bei dir im moment? Matcht $var1 die Zeile nicht? Findet keine Ersetzung statt?

          »» print OUTPUTDATEI $_;
          Du weisst, dass du in die OUTPUTDATEI den Dateiinhalt der INPUTDATEI in der Menge der Zeilen der Datei schreibst?

          »»

          Das Problem ist gelöst. Tatsächlich funktioniert folgender Code:

            
          #!usr/bin/perl  
          use utf8;  
          use warnings;  
          use strict;  
            
            
          open INPUTDATEI, "<", "e:\\---.txt" || die "Datei nicht geoeffnet, weil: $!";  
          open ZWEITEINPUTDATEI, "<", "e:\\----test.txt" || die "Datei nicht geoeffnet, weil: $!";  
          open OUTPUTDATEI, ">", "e:\\----.txt" || die "Datei nicht geoeffnet, weil: $!";  
            
          my @inputdatei = <INPUTDATEI>;  
          my @zweiteinputdatei = <ZWEITEINPUTDATEI>;  
          foreach (@zweiteinputdatei){  
          	my $var1 =$_;  
          	#chomp $var1;  
          						foreach (@inputdatei)  
          						{  
          										  
          										$_=~s#$var1#TEST#;  
          										my $var2 = $_;  
          										print OUTPUTDATEI "$var1"."-------->"."$var2\n";  
          						}  
          }
          

          Das Problem war nicht die Variableninterpolation (funktioniert auch ohne \Q). Vielmehr war tatsächlich (wie von Beat vermutet) das Line-Feed am Ende Schuld, dass kein match stattfand. chomp $var1 hat jedenfalls nicht funktioniert und das line-feed wie erhofft entfernt. oder es hat nur das line feed und nicht das newline entfernt (sind in windows doch unterschiedliche sachen oder?).

          Vielleicht kannst Du Deinen Satz:

          Du weisst, dass du in die OUTPUTDATEI den Dateiinhalt der INPUTDATEI in >>der Menge der Zeilen der Datei schreibst?

          noch erläutern. Ist zwar für das konkrete Problem u.U. unerheblich aber interssiert mich trotzdem.

          vielen dank für eure hilfe!

          mfg
          mrks

          1. Schönen guten Tag,

            Das Problem ist gelöst. Tatsächlich funktioniert folgender Code:

            #!usr/bin/perl
            use utf8;
            use warnings;
            use strict;

            open INPUTDATEI, "<", "e:\---.txt" || die "Datei nicht geoeffnet, weil: $!";
            open ZWEITEINPUTDATEI, "<", "e:\----test.txt" || die "Datei nicht geoeffnet, weil: $!";
            open OUTPUTDATEI, ">", "e:\----.txt" || die "Datei nicht geoeffnet, weil: $!";
            my @inputdatei = <INPUTDATEI>;
            my @zweiteinputdatei = <ZWEITEINPUTDATEI>;

            Sofern du die geöffneten Dateien nach dem speichern des Dateiinhalts in ein Array nicht mehr benötigst könntest du diese schonmal schließen.  
            
            > ~~~perl
              
            
            > foreach (@zweiteinputdatei){  
            > 	my $var1 =$_;  
            > 	#chomp $var1;  
            > 
            
            

            Wieso hast du hier chomp auskommentiert?

              				foreach (@inputdatei)  
              				{  
              								  
              								$_=~s#$var1#TEST#;  
              								my $var2 = $_;  
              								print OUTPUTDATEI "$var1"."-------->"."$var2\n";  
              				}  
            

            }

            
            >   
            > oder es hat nur das line feed und nicht das newline entfernt (sind in windows doch unterschiedliche sachen oder?).  
            
            <http://de.wikipedia.org/wiki/Zeilenvorschub>  
            
            >   
            > Vielleicht kannst Du Deinen Satz:  
            >   
            > >>Du weisst, dass du in die OUTPUTDATEI den Dateiinhalt der INPUTDATEI in >>der Menge der Zeilen der Datei schreibst?  
            >   
            > noch erläutern. Ist zwar für das konkrete Problem u.U. unerheblich aber interssiert mich trotzdem.  
            
            Deine vorletzter Perl-Code sah so aus:  
              
            
            > (...)  
            > ~~~perl
              
            
            > foreach (@zweiteinputdatei){  
            > 	$var1 =$_;  
            > 	foreach (@inputdatei)  
            > 	{  
            > 			$_=~s#\Q$var1#TEST#;  
            > 			print OUTPUTDATEI $_;  
            > 
            
            

            Du schreibst hier in die OUTPUTDATEI die vordefinierte Variable $_, die eine Zeile des Arrays @inputdatei ist. Da das einschreiben in die Datei in einer Schleife ist wird jede Zeile in die Datei geschrieben, somit also das ganze Array @inputdatei was der ganze Dateiinhalt der INPUTDATEI ist.
            Da du dich in einer weiteren Schleife (erstere) befindest wird die Schleife (zweitere) so oft durchgeführt wie die Datei ZWEITEINPUTDATEI Zeilen hat.
            Ich hoffe du verstehst was ich meine.

              }  
            

            }

            
            -- 
            suit: JavaScript ist nur das Schirmchen am Eisbecher - der Eisbecher muss auch ohne dem Schirmchen lecker sein.  
            Selfcode: sh:( fo:) ch:| rl:( br:< n4:( ie:{ mo:| va:) de:> zu:) fl:( ss:) ls:> js:) 
            
            1. Danke für die Erläuterung.
              Ich verstehe was Du meinst und bin, wegen dem von Dir erklärten Verhalten der Schleifen, auch schon auf Performanzprobleme gestoßen: Die Inputdatei wurde 2 GB groß und enhielt viele Wiederholungen.
              Aber auch das habe ich in den Griff bekommen und jetzt funktioniert alles wie geplant! Nochmals danke..

              mfg
              mrks

  2. Schönen guten Tag

    Der folgende Code

    ist ungetestet ...

    Dazu habe ich 2 verschachtelte foreach-Schleifen verwendet:

    foreach (@input_datei)
    {
    $var1 =$_;

    foreach (@input_datei_2){
    $_=~s#$var1#<a href="$1">$1</a>#;
    }

    }

    print @inputdatei;

    Prüfe erstmal was in $1 ist.  
    
    -- 
    suit: JavaScript ist nur das Schirmchen am Eisbecher - der Eisbecher muss auch ohne dem Schirmchen lecker sein.  
    Selfcode: sh:( fo:) ch:| rl:( br:< n4:( ie:{ mo:| va:) de:> zu:) fl:( ss:) ls:> js:)