Ersetzen von mehreren Wörtern in einer Zeile einer Datei
Suche-Ersetze
- perl
0 Beat0 Suche-Ersetze0 Beat
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
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
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
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
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
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