CGI/Perl Guide | Learning Center | Forums | Advertise | Login
Site Search: in

  Main Index MAIN
INDEX
Search Posts SEARCH
POSTS
Who's Online WHO'S
ONLINE
Log in LOG
IN

Home: Perl Programming Help: Advanced: Re: [CWDSolutions] Problem replacing only 1 peice of information in a text file! Please help.: Edit Log



rGeoffrey
User

Apr 29, 2002, 9:59 AM


Views: 3707
Re: [CWDSolutions] Problem replacing only 1 peice of information in a text file! Please help.

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.


Code
#!/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.


Code
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.


Code
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.


Code
		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.


Code
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".


Code
	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)


Edit Log:
Post edited by rGeoffrey (User) on Apr 29, 2002, 10:01 AM


Search for (options) Powered by Gossamer Forum v.1.2.0

Web Applications & Managed Hosting Powered by Gossamer Threads
Visit our Mailing List Archives