tags:

views:

439

answers:

6

My requirement is to replace a set of words in a given text file with a second set of words, which might be given from the command line or another file. Wanting to use Perl to do this, as the rest of my code is also in Perl.

So, if I have the following:

server name="${server1}" host="abc.com"
server name="${server2}" host="webcs.com"
server name="${server5}" host="httpvcs1.com"
server name="${server6}" host="xyz.com"
server name="${server7}" host="msg.com"

I wish to replace the strings 'server1', 'server2', 'server5', etc, with a different set of words. These might be placed in another file or given from the command line (whichever is more feasible).

Also, if, instead of just 'server1', 'server2', etc, I want to replace the 'server' word with say 'file', how would i go about making a regex for this replacement?

perl -pie 's/server\d{1-3}/myword/g' loginOut.txt > loginOut1.txt

The above will do a replacement for all words with 'myword'. But I want only the substring to be replaced.

A: 

Change your Regex to the following:

perl -pie 's/\{server/myword/g' loginOut.txt > loginOut1.txt
George Stocker
Note: I haven't actually tested this...
George Stocker
It also leaves the opening $ and closing }, so "foo=${server1}" would become "foo=$myword1}".
Hudson
Doesn't the -i option rewrite the input file so loginOut1.txt in this case will be empty?
Adrian Pronk
+2  A: 

The regular expression for your second question would be s/server/myword/g;. That matches (and substitutes) any occurrence of "server".

To replace server1, server2, etc., with a different string each, you could have a text file that contains the replacement rule, e.g.:

server1 abcd
server2 bcde
server3 cdef
etc.

You would then read in the date from the file into a hash, for instance,

my %dict;
while(<DICTFILE>){
    /(\S+)\s+(\S+)/;
    $dict{$1}={$2};
}

and after that proceed with the replacement:

while(my $line = <>){
    foreach my $s (keys %dict){
        $line =~ s/$s/$dict{$s}/g;
    }
    print $line;
}
Your dictionary build is missing a closing / on the search. my %dict; while(<DICTFILE>){ /(\S+)\s+(\S+); $dict{$1}={$2}; }
Hudson
where are you writing the values back to the original file?i wish to change the original file with the set of values.
gagneet
oops fixed those
When $s contains regex special characters (e.g. .[]{}\*?+) this will break.
Tomalak
This is not too bad. For in-place substitution, you could tie the file to an array with `Tie::File`.
Svante
+1  A: 

All the answers above have some flaw. You asked some way to

I wish to replace 'server1', 'server2', 'server5', etc. with something like 'file1', 'file2', 'file5', ..

The command for that is (in Windows prompt its -pe, not -pie):

perl -pe "s/\{server/\{file/g" in.txt > out.txt

and out.txt is:

server name="${file1}" host="abc.com"
server name="${file2}" host="webcs.com"
server name="${file5}" host="httpvcs1.com"
server name="${file6}" host="xyz.com"
server name="${file7}" host="msg.com"

I believe this is exactly what you wanted based on your latest comment.

Tuminoid
+1  A: 

You would simply need to take as much as you require to make it unique for your situation.

In this case you could do:

s/{server/{file/g;

Xetius
A: 

Try the following:

$what = 'server'; # The word to be replaced
$with = 'file';   # Replacement
s/(?<=\${)$what(?=[^}]*})/$with/g;
Sudden Def
A: 

You may want to try out Template Toolkit.


Here's an excerpt from the Template Toolkit Intro, Manual page:


The Template Toolkit is a collection of Perl modules which implement a fast, flexible, powerful and extensible template processing system. It is most often used for generating dynamic web content, although it can be used equally well for processing any kind of text documents.

At the simplest level it provides an easy way to process template files, filling in embedded variable references with their equivalent values. Here's an example of a template.

Dear [% name %],

It has come to our attention that your account is in 
arrears to the sum of [% debt %].

Please settle your account before [% deadline %] or we 
will be forced to revoke your Licence to Thrill.

The Management.

By default, template directives are embedded within the character sequences [% ... %] but you can change these and various other options to configure how the Template Toolkit looks, feels and works. You can set the INTERPOLATE option, for example, if you prefer to embed your variables in Perl style:

Dear $name,

It has come to our attention that your account is in 
arrears to the sum of $debt.

Perldoc page

Brad Gilbert