Hi,

I have written a small script that takes an infile, slurps it into an array, and makes a change to the file. Well that is my intention....

I can get the changes to be made using Regular Expressions because I can print and see my H1 tags are changed to H2 tags.

But I have not been able to figure out how to re-write the original file with the changes. I actually want to make these changes to the file, not just prove my loop is capable of making the changes with a print.

Here is my code:

open (INFILE, $ARGV[0]) or die "Error $ARGV[0]: $!\n";
@slurp = <INFILE>;

while (<@slurp>)
{
s#<(/?)H1>#<$1H2>#g;
}

print INFILE @slurp;

Mike,

You have several very good replies on perlguru but here is your code rewritten to work:

[I]# first open file for reading only[/I]
open (INFILE, $ARGV[0]) or die "Error $ARGV[0]: $!\n";
@slurp = <INFILE>;
close(INFILE);

[I]#now open file for overwriting[/I]
open (OUTFILE, ">", $ARGV[0])  or die "Error $ARGV[0]: $!\n";
for (@slurp){
   s#<(/?)H1>#<$1H2>#g;
   print OUTFILE;
}
close OUTFILE;

Hi KevinADC,

I want to understand what is missing or wrong with my script, not be handed a different script. Your script is great but it uses a for loop and I am using a while loop. Plus based on what I learned in class my code should be working so I know there has got to be one thing I am missing.

Your code causes me to have more questions - for example, why do you have to open the file two times once to read and once to write? Can you open it to write from the beginning and then stuff that into the array, modify the data, and print back to the file directly??? Here is an example of what I am saying and wondering why THIS does not work either:

[I]# Rewrite of kevin code, why don't this work?[/I]
open (INFILE, '<', $ARGV[0]) or die "Error writing to $ARGV[0]: $!\n";
@slurp = <INFILE>;
for ( @slurp )
{
    s#<(/?)H1>#<$1H2>#g;
    print INFILE $_;
}
close INFILE;

Mike,

You have several very good replies on perlguru but here is your code rewritten to work:

[I]# first open file for reading only[/I]
open (INFILE, $ARGV[0]) or die "Error $ARGV[0]: $!\n";
@slurp = <INFILE>;
close(INFILE);

[I]#now open file for overwriting[/I]
open (OUTFILE, ">", $ARGV[0])  or die "Error $ARGV[0]: $!\n";
for (@slurp){
   s#<(/?)H1>#<$1H2>#g;
   print OUTFILE;
}
close OUTFILE;

Your code does not work to edit the file because as was explained to you on perlguru you have opened the file for reading only. That is why I open it a second time as explained in the comments in the code I posted. You can try a file opening operator that allows you to read and write to a file at the same time, its either "+>" or ">+" I don't remember which.

You should use a "for" loop to process an array, not a "while" loop. "for" and "foreach" are optimized for the purpose of looping over an array, "while" is not.

Edit:

forget the +> and >+ suggestion. Read this for explanation:

http://perldoc.perl.org/perlopentut.html#Mixing-Reads-and-Writes

Here is the final word: use Tie::File or perls inplace editor if you want to edit a file in one pass.

# Rewrite of kevin code, why don't this work?
open (INFILE, '<', $ARGV[0]) or die "Error writing to $ARGV[0]: $!\n";
@slurp = <INFILE>;
for ( @slurp )
{
    s#<(/?)H1>#<$1H2>#g;
    print INFILE $_;
}
close INFILE;

The above doesn't work because "<" is the operator to open a file in read-only mode.

Kevin,

Thanks for the link you sent. That has great information in there. I can figure it out from here I think. I am understanding now the read vs. write different opens.

Thanks again,
Mike

KevinADC,

I read the link and had time to try some testing but no matter what I do the following code gets me the wrong end result.

Instead of changeing H1 to H2, I get the entire body of the file copied, as in an append, to itself and none of the H! tags are changed to H2.

Here is my code:

open (INFILE, "+< $ARGV[0]") || die "Can't open $ARGV[0]: $!\n";          
@slurp = <INFILE>;
while (<@slurp>)
{
  s#<(/?)H1>#<$1H2>#g;
  }
print INFILE @slurp;

Mike,

Like I said, don't bother with the + file open operator, use Tie::File or perls inplace editor. And why are you using "while (<@slurp>)" instead of "for(@slurp)". Its a little bit frustrating when I take the time to make suggestions and try to help a person and explain things to them but they seem to ignore what I have said.

Sorry Kevin,

I am not trying to get any script that can do the job. I know PERL is famous for having a hundred ways to do one thing but I am trying to get my code working. I had a course 2 weeks ago and in the course we used a while loop.
According to that webpage you gave me (which is awesome) it says +< is what I want.

#  open(WTMP, "+< /usr/adm/wtmp")
# || die "can't open /usr/adm/wtmp: $!";

But when I use it I get an append action instead of a modify as the site suggests. Append should be ">>" - very frustrating when you can't even believe what you are reading.

I guess I am stuck doing the READ and WRITE in two seperate opens, or the one liners, or the many other solutions you have given me.

Sorry. I was not ignoring your code. I did try those and they did work too. But as I am trying to learn PERL I am stuck in a trying to get my code working not just give me code that works mode.

Mike

This article has been dead for over six months. Start a new discussion instead.