Suche-Ersetze: Ersetzen von mehreren Wörtern in einer Zeile einer Datei

Hallo,

ich habe ein kleines Problem, ich versuche mittels PERL aus einer Datei in einer bestimmten Zeile, bestimmte Wörter zu finden und diese zu ersetzen, das ganze tue ich mittels den RegEx:

Die Datei sieht z.B. so aus:

__________________________
Ich bin der Inhalt
Ich auch
Und ich erst
Irgendwas SC-FTP SQLSERVER ADMIN ROOT C:\Data\datax D:\OutData\datay Datei.dat
Noch eine Zeile
Noch eine...
usw.
__________________________

Ich möchte nun aus der Zeile in der SC-FTP steht die nächsten 3 Wörter (SQLSERVER, ADMIN & ROOT) durch folgende Wörter ersetzen SERVERNAME, USER, PASSWORD. So ansich ist das kein Problem, nun ist es aber leider so das die Wörter SQLSERVER, ADMIN & ROOT variieren, sprich sie können jedesmal anders heißen, müssen aber trotzdem ersetzt werden...

Ich bin das ganze mal so angegangen:

  
#!C:\Perl\bin -w  
  
use feature qw/:5.10/;  
use strict;  
use warnings;  
  
my $buffer = '';  
my $data = $ARGV[0];  
my @data;  
my $replace = '';  
my $test = '';  
  
#Öffne Datei aus Benutzereingabe im readmodus  
open(DB, "$data") || die "Kann Datei nicht öffnen";  
@data = <DB>;  
close(DB);  
  
#Durchlaufe Array mit Dateiinhalt zeilenweise und suche zu ersetzende Teilstrings  
foreach $replace(@data)  
{  
 if(index($replace,"SC-FTP") != -1)  
  {  
   $test = $replace;  
   $test =~ m/^(.*)SC-FTP {1}([A-Za-z0-9]*) {1}([A-Za-z0-9]*) {1}([A-Za-z0-9]*) {1}(.*)$/;  
   $2 =~ s/[a-zA-z0-9]/Servername/;  
   $3 =~ s/[a-zA-z0-9]/User ID/;  
   $4 =~ s/[a-zA-z0-9]/Password/;  
   print $test;  
  }  
}  
  
#Schreibe aktualisierte Daten in die Datei zurück  
open(OUT, ">$data") || die "Can't write FTP-File!";  
print OUT "$replace\n";  
close(OUT);  

Mein Problem ist, das ich nur eine Warnmeldung bekomme á la:

Modification of a read-only value attempted!

Wo ist denn der Fehler bzw. wie kann ich das machen was ich vorhabe??

Liebe Grüße

  1. foreach $replace(@data)
    {
    if(index($replace,"SC-FTP") != -1)
      {
       $test = $replace;
       $test =~ m/^(.)SC-FTP {1}([A-Za-z0-9]) {1}([A-Za-z0-9]) {1}([A-Za-z0-9]) {1}(.*)$/;
       $2 =~ s/[a-zA-z0-9]/Servername/;
       $3 =~ s/[a-zA-z0-9]/User ID/;
       $4 =~ s/[a-zA-z0-9]/Password/;
       print $test;
      }
    }

    
    >   
    > Mein Problem ist, das ich nur eine Warnmeldung bekomme á la:  
    > Modification of a read-only value attempted!  
    > Wo ist denn der Fehler bzw. wie kann ich das machen was ich vorhabe??  
      
    Du versuchst. $2 .. $4 zu modifizieren, was nicht geht.  
    kommt man auch nur mit s/// aus  
      
    ~~~perl
      
    foreach( @data ){  
        s/^  \bSC-FTP\s  
             [A-Za-z0-9]*\s  
             [A-Za-z0-9]*\s  
             [A-Za-z0-9]*\s  
         /SC-FTP Servername User ID Password /x;  
    }  
    
    

    Bist du sicher dass du
        [A-Za-z0-9]*
    meinst und nicht
        [A-Za-z0-9]+

    mfg Beat

    --
    Woran ich arbeite:
    X-Torah
       <°)))o><                      ><o(((°>o
    1. Bist du sicher dass du
          [A-Za-z0-9]*
      meinst und nicht
          [A-Za-z0-9]+

      Ich bin mir ehrlich gesagt nicht sicher, aber soweit ich weiß, steht das + doch in den RegEx für EIN od. mehrmaliges Vorkommen, der * hingegen für KEIN od. mehrmaliges Vorkommen oder?

      Es muss ja nicht zwangsläufig ein Buchstabe drinstehen oder eine Zahl, es kann nur.

      Zu deinem Code, kannst du mir den bitte erklären ich steige da nicht ganz durch!

      Liebe Grüße

      1. Bist du sicher dass du
            [A-Za-z0-9]*
        meinst und nicht
            [A-Za-z0-9]+

        Ich bin mir ehrlich gesagt nicht sicher, aber soweit ich weiß, steht das + doch in den RegEx für EIN od. mehrmaliges Vorkommen, der * hingegen für KEIN od. mehrmaliges Vorkommen oder?

        Es muss ja nicht zwangsläufig ein Buchstabe drinstehen oder eine Zahl, es kann nur.

        Was die Sache erschwert
        "SC-FTP    unsinniger Text" enthält 4 whitespace Zeichen, deutet also auf drei "" Variablen hin.

        Codeerläuterung

        \b steht für eine Wordboundery ist also die Grenze zwischen \W und \w

        s///x
        der x Modifier erlaubt es, dass Leerzeichen nicht als Whitespace interpretiert werden. Dadurch kann ich eine RE Lesbar gestalten.
        Dafür muss ich jetzt aber whitespace explizit erwähnen: \s steht für genau ein Whitespace Zeichen.

        Ich schreibe nochmals, diesmal um klar zu machen, dass Werte optional sind.

        foreach( @data ){
            s/^  \bSC-FTP          \s
                 (?:[A-Za-z0-9]+)? \s
                 (?:[A-Za-z0-9]+)? \s
                 (?:[A-Za-z0-9]+)? \s
             /SC-FTP Servername User ID Password /x;
        }
        und komprimiert:

        s/^\bSC-FTP\s(?:[A-Za-z0-9]+)?\s(?:[A-Za-z0-9]+)?\s(?:[A-Za-z0-9]+)?\s/SC-FTP Servername User ID Password /;

        Du musst dir absolute Gewissheit über das Format des Strings nach SC-FTP verschaffen.

        mfg Beat

        --
        Woran ich arbeite:
        [link:http://www.elcappuccino.ch/cgi/tok.pl?extern=1-pub-com3306-1@title=X-
           <°)))o><                      ><o(((°>o
        1. Also ich habe mein Problem jetzt folgendermaßen gelöst, aber das ist mir viiiiel zu unsauber. Ich mags einfach nicht...auch wenns funktioniert!

            
          use feature qw/:5.10/;  
          use strict;  
          use warnings;  
          use Tie::File;  
            
          #Definiere globale Variablen  
          my $buffer = '';  
          my $data = $ARGV[0];  
          my $replace = '';  
          my $test = '';  
          my $FIRST = '';  
          my $SNAME = '';  
          my $UID = '';  
          my $PWD = '';  
          my $LAST = '';  
          my @data;  
          my $new;  
            
          #Öffne Datei aus Benutzereingabe im readmodus  
          open(DB, "$data") || die "Can't open FTP-File!";  
          @data = <DB>;  
          close(DB);  
            
          #Durchlaufe Array mit Dateiinhalt zeilenweise und suche zu ersetzende Teilstrings  
          foreach $replace(@data)  
          {  
              if(index($replace,"SC-FTP") != -1)  
                 {  
                  $replace =~ m/^(.*)SC-FTP( {1}[A-Za-z0-9]*)( {1}[A-Za-z0-9]*)( {1}[A-Za-z0-9]*)( {1}.*)$/;  
                  $FIRST=$1;  
                  $SNAME=$2;  
                  $UID=$3;  
                  $PWD=$4;  
                  $LAST=$5;  
                  $SNAME =~ tr/[a-zA-z0-9]/X/;  
                  $UID =~ tr/[a-zA-z0-9]/X/;  
                  $PWD =~ tr/[a-zA-z0-9]/X/;  
                  $buffer=$FIRST;  
                  $buffer.=$SNAME;  
                  $buffer.=$UID;  
                  $buffer.=$PWD;  
                  $buffer.=$LAST;  
                  $buffer.="\n";  
                  $replace = $buffer;  
                 }  
              }  
          #Schreibe aktualisierte Daten in die Datei zurück  
          open(OUT, ">$data") || die "Can't write FTP-File!";  
          foreach $new(@data)  
          {print OUT $new;}  
          close(OUT);  
          
          

          Das muss doch schaffbar sein....irgendwie.

          Das Problem ist das ich nie wirklich weiß wie der String aussieht, ich weiß nur eines nach SC-FTP kommt servername (ein leerzeichen) username (ein leerzeichen) passwort (ein leerzeichen) und noch irgendwas.

          Und ich muss diese 3 Wörter durch IRGENDWAS ersetzen X's oder Wörter.

          Liebe Grüße

          1. Also ich habe mein Problem jetzt folgendermaßen gelöst, aber das ist mir viiiiel zu unsauber. Ich mags einfach nicht...auch wenns funktioniert!

            Wenn's funktioniert, scheint Dein RegExp ja zumindest das Muster richtig abzubilden. Jetzt musst Du nur noch die Hinweise von Beat mit meinen Hinweisen zu Tie::File kombinieren.

            Siechfred

            --
            Obacht, hinter jedem noch so kleinen Busch könnte ein Indianer sitzen!