Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations strongm on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

replacing strings from one file into another 1

Status
Not open for further replies.

samdaman

Technical User
Oct 23, 2002
23
NZ
Hi there.

So this is my 2nd week perl scripting, and im starting to get the ropes now.

I have two text files, one is created by another perl script that is an output from a cisco router, the other is a text file that lists "Dialer101 to Amsterdam" for example. I am trying to get my script to replace the dialer name with the actual name.

Here is what I have so far

#!e:\perl\bin


$s_output = "cismultilink.txt";
$new_output = "named_output.txt";
$location = "location.txt";


open (SOUT, &quot;<$s_output&quot;) or die &quot;cant open $s_output: $!&quot;;
open (NOUT, &quot;+>$new_output&quot;) or die &quot;cant open $new_output: $!&quot;;
open (LOCATION, &quot;<$location&quot;) or die &quot;cant open $location: $!&quot;;

my ($inline);
my (@inlinearray);
while ($inline = <LOCATION>)
{
if (substr ($inline,0,1) ne &quot;#&quot;)
{@inlinearray = split &quot;\t&quot;,$inline;
$inlinearray[0] =~ s/[ \t\n\r]*$//g;
$inlinearray[0] =~ s/^[ \t\n\r]*//g;
$dialer = $inlinearray[0];
$dialername = $inlinearray[1];


foreach $pattern ($dialer) {
my $re = qr/$pattern/;
foreach $line(@lines) {
if ($line =~ $re) {
print $inlinearray[1]($line);
print NOUT;
}
}


}


}



}


I guess I could be doing this totally wrong, but then thats why I am asking for help.

Kind regards

Sam
 
First off there is some missing code, particularly for filehandling. I assume @lines is the contents of SOUT.

You can use 'chomp' to strip off end-of-line characters from each line, and whitespace (apart from the end-of-line character) can be handled by the \s metacharacter in a regex. Using the ^ and $ anchors (begin and end of line) means you don't need the /g modifier.

You are also not doing any substitution, just printing stuff to STDOUT. Hopefully you can follow the code below and change it to what you actually need:

open (SOUT, &quot;<$s_output&quot;) or die &quot;cant open $s_output: $!&quot;;
open (NOUT, &quot;+>$new_output&quot;) or die &quot;cant open $new_output: $!&quot;;
open (LOCATION, &quot;<$location&quot;) or die &quot;cant open $location: $!&quot;;

my $bigline = join(&quot;&quot;,<SOUT>); # slurp file into memory
close SOUT;

while (my $inline = <LOCATION>) {
chomp $inline; # strip off end-of-line characters

unless ($inline =~ /^#/) {
my @inlinearray = split &quot;\t&quot;,$inline;
$inlinearray[0] =~ s/^\s+//; # strip off leading white space
$inlinearray[0] =~ s/\s+$//; # strip off trailing white space

$bigline =~ s/$inlinearray[0]/$inlinearray[1]/gs;
}
}

print NOUT $bigline;
close NOUT;


Note that the /s modifier on the $bigline regex, means treat the string as a single line, thus it cross the end-of-line character boundaries.

Barbie
Leader of Birmingham Perl Mongers
 
Hi Barbie

Thanks for your reply, it has definately pointed me in the right place. I have managed to get it almost working perfectly. The last thing is that when the script finds a match, it starts to replace it with something from the location script. For example in my location file I have the following data

Dialer1 Amsterdam
Dialer2 Birmingham ;-)
...
Dialer10 London

So when the SOUT file has Dialer10 listed, it returns Amsterdam. I guess this is also an easy fix, so I am looking for the answer now by playing with ur script. Is there a quick fix for this?

Also if you have time, (and only if you do) I have written my understanding of the things you have done, perhaps you could &quot;tick, or X&quot; the things i have understood correctly, or incorrectly

Thanks again Barbie

Sam


$s_output = &quot;cismultilink.txt&quot;;
$new_output = &quot;named_output.txt&quot;;
$location = &quot;location.txt&quot;;

#as no substitution is needed, you have removed the #handles I listed below

open (SOUT, &quot;<$s_output&quot;) or die &quot;cant open $s_output: $!&quot;;
open (NOUT, &quot;+>$new_output&quot;) or die &quot;cant open $new_output: $!&quot;;
open (LOCATION, &quot;<$location&quot;) or die &quot;cant open $location: $!&quot;;

#you join the whole SOUT document into one line into mem

my $bigline = join(&quot;&quot;,<SOUT>); # slurp file into memory
close SOUT;

#loops through location document, striping off end of line #charachters like spaces?

while (my $inline = <LOCATION>) {
chomp $inline; # strip off end-of-line characters

unless ($inline =~ /^#/) {
my @inlinearray = split &quot;\t&quot;,$inline;
$inlinearray[0] =~ s/^\s+//; # strip off leading white space
$inlinearray[0] =~ s/\s+$//; # strip off trailing white space

#replace dialernumber with dialername make global, but not #sure what the s is for

$bigline =~ s/$inlinearray[0]/$inlinearray[1]/gs;
}
}

print NOUT $bigline;
close NOUT;
 
Change the following:

$bigline =~ s/$inlinearray[0]/$inlinearray[1]/gs;

to:

$bigline =~ s/\b$inlinearray[0]\b/$inlinearray[1]/gs;

This will ensure that the replacement only occurs if there are no other word characters either side of the word you want to replace.

Thus, 'abcDialer10xyz' wouldn't get replaced, but 'abc Dialer10,xyz' would.

Your assumptions to the other bits of code are correct, apart from the first one. You still need the filhandles.

The slurp line is a handy one-liner to grab a whole file into a scalar. In order to do the replace later, the /s modifier on the $bigline regex above tells the regex engine to treat the string as a single line. Otherwise it would only replace matches within the characters upto the first end-of-line character.

Barbie
Leader of Birmingham Perl Mongers
 
Here is what I have tried so far, but either I get the same result as before, or it does not match anything.

Kind regards

Sam



open (SOUT, &quot;<cismultilink.txt&quot;) or die &quot;cant open cismultilink.txt: $!&quot;;
open (NOUT, &quot;+>named_output.txt&quot;) or die &quot;cant open named_output.txt: $!&quot;;
open (LOCATION, &quot;<Location.txt&quot;) or die &quot;cant open Location.txt: $!&quot;;

@lines=<SOUT>;
$bigline = join(&quot;&quot;,@lines); # slurp file into memory
@lines = split /\r|,/, $bigline; #split line for data needed
#print &quot;$bigline&quot;;
close SOUT;

while (my $inline = <LOCATION>) {
chomp $inline; # strip off end-of-line characters
unless ($inline =~ /^#/) {
my @inlinearray = split /\t/,$inline;
$inlinearray[0] =~ s/^\s+/\s/; # strip off leading white space
$inlinearray[0] =~ s/\s+$/\s/; # strip off trailing white space
foreach $line(@lines) { #tried to say that the expression must match until the carrige return or ,
if ($line =~ /(?=\r|,)/) {
$line=~ s/$inlinearray[0]/$inlinearray[1]/gs
}
}
}
}
#print $bigline;
print &quot;@lines&quot;;
#print NOUT $bigline;
close NOUT;


 
Try:

$line=~ s/\b$inlinearray[0]\b/$inlinearray[1]/gs

I note that you've gone back to the @lines for storing the lines. This method is actually alot slower for what you want to do rather that letting the regex engine cope with it, as the regex engine is written in C. However, to be more efficent on memory read the file in as:

while(<SOUT>) {chomp;push @lines, $_}
close SOUT;



Barbie
Leader of Birmingham Perl Mongers
 
Your a star it works really well. I guessed the answer was something like this, and had tried lots of matching operations. When nothing seemed to work, I added the @lines.

Thanks very much

Kind regards

Sam
 
Hi Barbie

So I have incorporated this into my script now (at the bottom)

A summary is that this script takes an output from a cisco router and saves it to a file called cismultilink.txt.
Then the script you helped me create takes the output from this file and then does the substition. My question is can I do this without saving it to the file, then reopening the file and saving it again? My guess is rather than save the information to a file, define this in memory, but how?

Thanks and kind regards

Sam


use Net::Telnet::Cisco;

# Globals.
our $LOGIN = '';
our $PASS = 'password';
our $ENPASS = 'password';


# Reading file for routers
my ($host);

open (CONFIG, &quot;routers.txt&quot;);
open (CISDIALOUTPUT, &quot;>cismultilink.txt&quot;);
my ($inline);
my (@inlinearray);
while ($inline =<CONFIG>)
{
if (substr ($inline,0) ne &quot;#&quot;)
{
@inlinearray = split &quot;,&quot;,$inline;
$inlinearray[0] =~ s/[ \t\n\r]*$//g;
$inlinearray[0] =~ s/^[ \t\n\r]*//g;
$host = $inlinearray[0];
#Router automation

my $session = Net::Telnet::Cisco->new( Host => $host );
$session->login( $LOGIN, $PASS );

if ( $session->enable( $ENPASS ) )
{
$session->cmd('term length 0');
@intopen = $session->cmd( 'show interface summary | include Dialer');
@multilink = $session->cmd( 'show ppp multilink' );
my ($count);
$count = 0;
#print &quot;\n$inlinearray[0]\n\n&quot;;
#print &quot;Dialers Open\n\n&quot;;
print CISDIALOUTPUT &quot;\n$inlinearray[0]\n\n&quot;;
print CISDIALOUTPUT &quot;Dialers Open\n\n&quot;;
while ($intopen[$count])
{
if ($intopen[$count] =~/^[ \t]*\*[ \t]+/)
{
$intopen[$count] =~ s/^[ \t]*\*[ \d\t]*//g;
$intopen[$count] =~ s/[ \t]+\d[ \d\t\n\r]*$//g;
#print &quot; $intopen[$count]\n&quot;;
print CISDIALOUTPUT &quot; $intopen[$count]\n&quot;;
}
$count++;
}
$count = 0;
#print &quot;\nTotal Lines Open\n\n&quot;;
print CISDIALOUTPUT&quot;\nTotal Lines Open\n\n&quot;;
while ($multilink[$count])
{
if ($multilink[$count] =~ /Dialer|Member/)
{
$multilink[$count] =~ s/[ \t\n\r]*$//g;
$multilink[$count] =~ s/^[ \t\n\r]*//g;
#print &quot; $multilink[$count]\n&quot;;
print CISDIALOUTPUT &quot; $multilink[$count]\n&quot;;
}
$count++;
}
}
else
{
warn &quot;Can't enable: &quot; . $session->errmsg;
}
}
}
close (CISDIALOUTPUT);
close (CONFIG);
open (LOCATION, &quot;<Location.txt&quot;);
open (CISDIALOUTPUT, &quot;<cismultilink.txt&quot;);
my $bigline = join(&quot;&quot;,<CISDIALOUTPUT>); # slurp file into memory

while (my $inline2 = <LOCATION>) {
chomp $inline2; # strip off end-of-line characters
unless ($inline2 =~ /^#/) {
my @inlinearray2 = split &quot;\t&quot;,$inline2;
$inlinearray2[0] =~ s/^\s+//; # strip off leading white space
$inlinearray2[0] =~ s/\s+$//; # strip off trailing white space
$bigline =~ s/\b$inlinearray2[0]\b/$inlinearray2[1]/gs;
}
}
print $bigline;

close (CISDIALOUTPUT);
close (LOCATION);

exit 0;


__END__
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top