Beefy Boxes and Bandwidth Generously Provided by pair Networks
more useful options
 
PerlMonks  

How to Put a Loop in my 1st Program

by shemyaza (Novice)
on Nov 21, 2001 at 19:17 UTC ( [id://126775]=perlquestion: print w/replies, xml ) Need Help??

shemyaza has asked for the wisdom of the Perl Monks concerning the following question:

I am writing my first perl program at the moment (see below). What I want to do is insert the contents of general.txt into the start of all of the files listed in a file called files.txt. The code below works for the first file listed in files.txt but I can't figure out how to get it to loop through all of the files in files.txt. I thought of counting the number of lines in files.txt and using a 'for' loop, but that's a bit inelegant. Can you help? S.
#!/usr/local/bin/perl open (TEXT,"general.txt") || die "Could not open file: $! \n"; $addthis=join("", <TEXT>); close (TEXT); open (FILES,"files.txt") || die "Could not open file: $! \n"; # Start to loop here??? or after the next group of statements? $line=<FILES>; chomp $line; open (DATA,"$line") || die "Could not open file: $! \n"; $tothis=join("", <DATA>); close (DATA); $newrecord=$addthis.$tothis; open (DATA,">$line") || die "Could not write to: $! \n"; print "$line\n"; print DATA $newrecord; close (DATA);

Replies are listed 'Best First'.
Re: How to Put a Loop in my 1st Program
by sifukurt (Hermit) on Nov 21, 2001 at 19:42 UTC
    I tried to follow your methodology as closely as possible. There are easier and/or more efficient ways of doing what you're trying to do, but personally, I'd worry about style after you're a little more comfortable with the language as a whole. Not to discount style, mind you, but as with a spoken language, you don't worry about writing a sonnet or a haiku until you've learned how to write a sentence or paragraph.
    #!/usr/local/bin/perl use strict; use vars qw( $addthis $tothis $newrecord ); open (TEXT, "general.txt") || die "Couldn't open file: $|\n"; $addthis = <TEXT>; close (TEXT); undef $/; open (FILES,"files.txt") || die "Could not open file: $! \n"; while ( <FILES> ) { open ( DATA, $_ ) || die "Could not open file: $|\n"; $tothis = <DATA>; close (DATA); $newrecord = $addthis . $tothis; open ( DATA, "> $_" ) || die "Could not write to file: $|\n"; print $_, "\n"; print DATA $newrecord; close (DATA); } close (FILES);
    Since you're treating all of the files as individual strings, you can do the undef $/; business. $/ is the input record separator, and since we aren't limiting the scope (i.e., putting undef $/; inside a subroutine, for example), it is a global change and will apply to all subsequently read files. And in this case, I think a 'while' loop is one of the easier ways to setup the looping. I don't want this to sound like a shameless plug, but I wrote the module File::Butler, and it was specifically designed to handle this sort of thing. And since File::Butler does all of the grunt work for you, you don't need to worry about most of it. Using File::Butler, you could re-write the above as this:
    #!/usr/local/bin/perl use strict; use File::Butler; use vars qw( @newstuff @files ); Butler( "general.txt", "read", \@newstuff ); Butler( "files.txt", "read", \@files ); foreach my $file ( @files ) { Butler( $file, "prepend", \@newstuff ); }
    I hope this helps. Welcome to the Perl Fraternity, btw. We'll teach you the secret handshake later. :-)

    Update: Pursuant to discussion with tilly on the use of our vs. use vars, I've modified the above code to use vars rather than our as I had done originally. I wasn't aware that our differed so much in theory and practice.

    Update2: Eeeeeek! Hofmator is absolutely correct. I had undef $/; in the wrong place. Thanks for catching that, Hofmator. I moved it down a few lines, and it will work correctly now. I'm now performing undef $/; after we've read in "files.txt".

    ___________________
    Kurt

      Since you're treating all of the files as individual strings, you can do the undef $/; business.

      I don't think so, you want to read the filenames stored in 'files.txt' line by line - which your solution doesn't do. So I'd go for something like this:

      open(FH, 'filename') or die $!; my $text = do {local $/; <FH>}; close FH;

      For a complete treatmeant of many possibilities and discussions on how to slurp a file read the very informative Slurp a file.

      -- Hofmator

Re: How to Put a Loop in my 1st Program
by MZSanford (Curate) on Nov 21, 2001 at 19:26 UTC
    Rather than give a working copy, here is something to point you in the right direction :

    while (my $line = <FILES>) { # open the file ($line) as DATA # manipulate the file # close(DATA); } close(FILES);

    i had a memory leak once, and it ruined my favorite shirt.
Re: How to Put a Loop in my 1st Program
by frankus (Priest) on Nov 21, 2001 at 19:58 UTC

    Congratulations on a fine choice of programming language ;o)

    A few really good habits to start with are:

    #!/usr/bin/perl -w use strict;
    This takes away the niceness of not having to declare variables, but makes spotting bugs waaaay faster ;)

    $addthis=join("", <TEXT>);
    Whoa!! Nice use of join, it makes sense now I think about it. I'd suggest using ' instead of " as " interpolates stuff, and if you don't need it use ' instead ;)
    open (FILES,"files.txt") || die "Could not open file: $! \n";
    I prefer: open FOO,'foo.txt' or die "$! foo.txt\n";


    Maybe use a while loop or a for loop, as for loops can traverse arrays too.

    for (<FILES>){ chomp; # each item of the array is placed in $_ for the scope of t +he for unless (open (D,$_)){ # no need to wrap the variable in quotes print STDERR "$!:$_\n"; # In case the failure to read one file + isn't critical next; # Skips all the other commands in the loop and goes to t +he next iteration. } my $newrecord=$addthis.join('',<D>); close(D); open (D,">$_") || die "Could not write to: $! \n"; print "$_\n"; print D $newrecord; close (D) }

    Watch yourself here, DATA is a reserved word IIRC like:

    #!/usr/bin/perl -w use strict; $someperl=<DATA>; __DATA__ Some data
    Now $someperl should contain "Some data".

    --

    Brother Frankus.

    ¤

Re: How to Put a Loop in my 1st Program
by c-era (Curate) on Nov 21, 2001 at 19:28 UTC
    You want to use a while loop,
    #!/usr/local/bin/perl open (TEXT,"general.txt") || die "Could not open file: $! \n"; $addthis=join("", <TEXT>); close (TEXT); open (FILES,"files.txt") || die "Could not open file: $! \n"; # Start to loop here??? or after the next group of statements? while ($line=<FILES>){ chomp $line; open (DATA,"$line") || die "Could not open file: $! \n"; $tothis=join("", <DATA>); close (DATA); $newrecord=$addthis.$tothis; open (DATA,">$line") || die "Could not write to: $! \n"; print "$line\n"; print DATA $newrecord; close (DATA); }
Re: How to Put a Loop in my 1st Program
by shemyaza (Novice) on Nov 21, 2001 at 22:35 UTC
    Thanks for your help! I will try and avoid the temptation of studying the 'full' answers until I've tried to sort it out myself with your helpful tips. I'm afraid I can't take credit for my use of 'join'! I found that on the perlmonks site yesterday using google. It's such a great site I just had to register, so here I am! :-) S.

      Studying full answers isn't necessarily bad, especially not when you learn from them.

      Did you read the semi-official Perl literature yet? "Programming Perl" (aka the Camel book) might be too hard, but "Learning Perl" should be easier (I haven't read it). Both are in their third editions already, and more information can be found at http://perl.com/ or http://oreilly.com/ or in the better book stores. (No, they don't pay me for this, and if I don't say it, someone else will. These books are recommended to every Perl newbie here :-))

      Or try the Tutorials section in the Monastery. It has tutorials on basic stuff like scalars and loops, but also on more advanced topics.

      But I think that reading a book is usually a smart idea, as these books are more coherent than loose tutorials, and paper reads differently.

      Good luck, and don't forget to have fun in the process :-)

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://126775]
Approved by root
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others surveying the Monastery: (5)
As of 2024-03-28 16:55 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found