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 Mike Lewis on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Find and Replace multiple strings

Status
Not open for further replies.

jess916

Programmer
Aug 26, 2008
11
0
0
US
I am using the script below to find and replace while comparing variable names. Basically there are two sperate files where I extract a register name. When two registers match I need the register name to replaced with an old name. the problem with the script below is that it will do the replace and then print out the ENTIRE contents of the file but I only need to replace the contents and wait to print the contents once. anyone have any suggestions?

Code:
##### SAMPLE CODE
my $Adat_file = "prelim.dat";
my @registers = &read_dat_file($Adat_file); #new registers
my $Old_regs = "Compatible.txt";
my @Bregisters = &read_old_regs($Old_regs);
my $Acount = @Bregisters;

#change contents of old file
my $file = "prelim.dat";
#$file=@_;
my @contents =undef;
open(FILE, "+<$file") || die "Can't Find File: $file\n";

foreach my $register(@registers) {     # loop through all the registers
    my $Aname = $register->{name};
    foreach my $Bregister(@Bregisters) {
	   my $Bnewname = $Bregister->{newname};
	   my $Boldname = $Bregister->{oldname};
	   my $Bprefix = $Bregister->{prefix};
	   if ($Aname eq $Bnewname) { # match is found
		   while($_=<FILE>) {
		   my $changes += s/R2_$Aname/$Bprefix_$Boldname/i;
		   push(@contents,$_);
		   next;
		   }	
	   }
	   seek(FILE,0,0);
     }
}
print FILE  (@contents);
close(FILE);
 
Why not use Tie::File or perls inplace editor?

------------------------------------------
- Kevin, perl coder unexceptional! [wiggle]
 
jess916, if you, like me, prefer to use modules a minimum, here are some suggestions.
You are reading the file prelim.dat once at beginning, then every time (!) you find a match. Also, [tt]@contents[/tt] will finally contain the contents of this file replicated a number of times equal to the number of matches.
You should follow this logic:
1)Read the whole of compatible.txt, the create a hash containing all the newname's in it
2)Read prelim.dat line by line, and:
2.1)check for any register name in it (I assume there can be at most one per line, but you can easily accept also multiples)
2.2)check if the register name exists in the hash above
2.3)if it does:
2.3.1)replace with the oldname
2.3.2)rewind (seek) the file to the beginning of present line
2.3.3)rewrite the line
However the preceding will work only if register names are all the same length. If this isn't true you need a temporary file; this more general option is used in the following.
I cannot propose a full rewriting of your code, as I don't know the structure of the file prelim.dat; let's assume that a sub [tt]extract_name_from_line[/tt] will return the single register name that's contained in it, and [tt]undef[/tt] if there isn't.
This should do what you need (untested)
Code:
my$Old_regs="Compatible.txt";
my@Bregisters=read_old_regs($Old_regs);
my%hash_of_newnames;
map{$hash_of_newnames{uc$$_{newname}}="$$_{prefix}_$$_{oldname}"}@Bregisters;
  #change contents of old file
open(FILE,'prelim.dat')||die"Can't Find File: prelim.dat\n";
open(TMP,'>prelim.tmp')||die"Can't Open File: prelim.tmp\n";
my$Aname;
while(<FILE>){
  if($Aname=extract_name_from_line($_)&&exists$hash_of_newnames{uc$Aname}){
    s/R2_$Aname/$hash_of_newnames{uc$Aname}/;
  }
  print TMP;
}
close(FILE);
close(TMP);
rename'prelim.tmp','prelim.dat';
Note:as you had a case insensitive switch in the regex, I assumed the compare of names should be case insensitive, that's why they are all [tt]uc[/tt]'d in [tt]%hash_of_newnames[/tt] : of course you should correct this, if it's not required.

Franco
: Online engineering calculations
: Magnetic brakes for fun rides
: Air bearing pads
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top