
rGeoffrey
User
Apr 29, 2002, 9:59 AM
Post #4 of 4
(4041 views)
|
Re: [CWDSolutions] Problem replacing only 1 peice of information in a text file! Please help.
[In reply to]
|
Can't Post
|
|
Here is what I have come up with. I did not actually write out the files and have left those 6 lines commented out as I have a different environment than you and it was not really the point of the exercise. You will also want to throw out my strange if (0) where I set my directory names without being forced to comment yours out.
#!/usr/local/bin/perl use strict; my ($iplist, $superuserpath, $sourcedir, $donedir); if (0) { #Directories listed in the original post $iplist = "../iplist.txt"; $superuserpath = "/home/www/ipchanger/newone/"; } else { #Directories used while testing in a different environment $iplist = "iplist.txt"; $superuserpath = "samples"; $sourcedir = "samples"; $donedir = "output" } #Suck dem changes list is $changelist[x][0]=old ip $changlist[x][1]=new ip my @changelist; my $i=0; open (CNG, $iplist) || die "No Change List, $!"; while (<CNG>) { chomp; my @tmp = split(/=/); push (@changelist, \@tmp); print "$i - $tmp[0] will be $tmp[1]\n"; $i++; } close (CNG); print "Kewl Stuff, I found ", scalar (@changelist), " changes to do...\n"; #These are protected files that are not to be manipulated each name will be #a key in the hash so we can see if the key exists. The value is irrelevant. my %protected = map { $_ => 1 } qw (. .. ipchanger.pl); opendir(DIR, $sourcedir) || die "Can't open superuser path, $!"; while (my $aname=readdir(DIR)) { if (-d "$sourcedir/$aname") { print "\nfound Directory '$aname'\n"; } elsif (exists ($protected{$aname})) { print "\nfound a protected file '$aname'\n"; } else { open (MOL,"$sourcedir/$aname") || die "Cant open the file $sourcedir/$aname - NO FUN, $!"; local $/; # Disable Input Record Separator my $molestme=<MOL>; # Ever seen spaceballs? "Suck Suck Suck" close (MOL); # open (FIL,">./backup/$aname\.bak") || die "Cant Write Output, $!"; # print FIL $molestme; # close (FIL); my $filesize=length($molestme); print "\nI have found a file $aname with $filesize Bytes to pillage in it.\nAnd Away We GOOOO \n"; foreach my $pair (@changelist) { my $was =$pair->[0]; my $is =$pair->[1]; # MAGIK SPOT -- my $ct = ($molestme=~s/$was/$is/g); print "$was is now $is, changed $ct times\n" if ($ct); } # open (FIL,">$aname") || die "Cant Write Output, $!"; # print FIL $molestme; # close (FIL); } } close (DIR); Now to go over several of the changes... It is now 'use strict' safe as I have chased down all the variables and added my.
open (CNG, $iplist) || die "No Change List, $!"; while (<CNG>) { chomp; my @tmp = split(/=/); push (@changelist, \@tmp); print "$i - $tmp[0] will be $tmp[1]\n"; $i++; } By declaring 'my @tmp' inside the loop, we get a new one each time. And then we can push a pointer to the new small array of two elements to the end of the big array changelist. Thus we get our array of arrays and never have to use subscripts. $i was kept only for the print statement. And I chomped before the split to avoid the two regular expressions, although only one should have been needed as the part before the equals should not have had one.
my %protected = map { $_ => 1 } qw (. .. ipchanger.pl); #.... } elsif (exists ($protected{$aname})) { print "\nfound a protected file '$aname'\n"; Rather than a long list of file names with 'eq' and '&&' we can use a hash where the keys are the protected filenames. All we have to do is check to see if the filename exists as a key in the hash to know that it is special case.
foreach my $pair (@changelist) { my $was =$pair->[0]; my $is =$pair->[1]; # MAGIK SPOT -- my $ct = ($molestme=~s/$was/$is/g); print "$was is now $is, changed $ct times\n" if ($ct); } The for loop is often better replaced with a foreach in Perl. In this case we do not need to keep $i around and can deal with the whole small array at once. $pair is a pointer the the inner array and we can use it to fill $was and $is. Remember that as $pair is a scalar that points to an array and not an actual array you will need to dereference its parts with the '->' notation. I also added the $ct variable to capture how many times a substitution was made and the print statement will show that fact. Actually the print statement will only print if a subsitution was made to reduce clutter in the output stream.
opendir(DIR, $sourcedir) || die "Can't open superuser path, $!"; When reading a file or directory and the whole filename is already in a variable it is much better to not wrap the single variable in double quotes. Adding the quotes forces perl to create a new string that is exactly the same as the variable that was already known. This does not apply to writing of course as the writing will need to add a '>' to the front of the filename. Also you should always include $! in your die statements to learn a little more about the error. And you should not end your error message with a new line because you can get $! to tell you more if you do not end with "\n".
if (-d "$sourcedir/$aname") { Remember that the output from readdir is the filename without any directory information. To use the filename when you are dealing with a directory other than where you currently are you usually have to use it as $dir/$filename. One other thing to consider, especially as the number or size of your files increases, is that it might be better to read from $sourcedir and write your new files to $outputdir rather than read from $sourcedir, write an exact copy in $backupdir and then a modified copy in $sourcedir. It is probably much easier to move the directories around after the change. Edited to fix a typo.
(This post was edited by rGeoffrey on Apr 29, 2002, 10:01 AM)
|