LinuxQuestions.org
Share your knowledge at the LQ Wiki.
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 10-17-2009, 02:47 AM   #1
SuperDude123
Member
 
Registered: Nov 2008
Posts: 158

Rep: Reputation: 30
loop problem in perl


I'm trying to make my script change a value by increments of 1, and then spit out a filename001, then filename002...etc. As of now, filename001 works, but filename002 and up are just blank. Can you tell me where I did the error and how to fix it?

while ($n<10) {
open (OUT, ">filename00".$n.".txt");

while (<IN>) {


$found1 = index($_, $search1);
if ($found1 >= 0) {
$sep1 = index($_, "=");
$temp1 = substr($_, 0, $sep1 +1);
$newvalue1 = $newvalue1 + $increments;
print OUT "$temp1$newvalue1 \n";
}


else {

$found2 = index($_, $search2);
if ($found2 >= 0) {
$sep2 = index($_, "=");
$temp2 = substr($_, 0, $sep2 +1);
$newvalue2 = $newvalue2 + $increments;
print OUT "$temp2$newvalue2 \n";
}


else {
print OUT $_;
}}


}
$n = $n+1;
}


close OUT;
close IN;
 
Old 10-17-2009, 03:23 AM   #2
bartonski
Member
 
Registered: Jul 2006
Location: Louisville, KY
Distribution: Fedora 12, Slackware, Debian, Ubuntu Karmic, FreeBSD 7.1
Posts: 443
Blog Entries: 1

Rep: Reputation: 47
I took the liberty of running perltidy across your code:

Code:
#! /usr/bin/perl

while ( $n < 10 ) {
    open( OUT, ">filename00" . $n . ".txt" );

    while (<IN>) {

        $found1 = index( $_, $search1 );
        if ( $found1 >= 0 ) {
            $sep1 = index( $_, "=" );
            $temp1 = substr( $_, 0, $sep1 + 1 );
            $newvalue1 = $newvalue1 + $increments;
            print OUT "$temp1$newvalue1 \n";
        }

        else {

            $found2 = index( $_, $search2 );
            if ( $found2 >= 0 ) {
                $sep2 = index( $_, "=" );
                $temp2 = substr( $_, 0, $sep2 + 1 );
                $newvalue2 = $newvalue2 + $increments;
                print OUT "$temp2$newvalue2 \n";
            }

            else {
                print OUT $_;
            }
        }

    }
    $n = $n + 1;
}

close OUT;
close IN;
This makes it clear that you're not closing "OUT" on every iteration of your while loop.
 
Old 10-17-2009, 07:21 AM   #3
Telemachos
Member
 
Registered: May 2007
Distribution: Debian
Posts: 754

Rep: Reputation: 60
Some tips and thoughts:
  • You aren't using warnings or strict, but you really should. Start all your scripts (even short ones) this way, until you're completely sure you know why and how to turn off the enforcers locally:
    Code:
    use strict;
    use warnings;
  • If you need to create a group of filenames such as 'filename001.txt, filename002.txt' etc., there are easier, cleaner to read ways to do that. Here's one thought:
    Code:
    my @out_handles = map { $_ = 'filename00' . $_ . '.txt' } (0..9);
    
    # Just to show what you get; remove later
    print "$_\n" for @out_handles;
    You can then iterate over the @out_handles array. (It's not a great variable name, but you get the idea.)
  • You should take a look at the newer, three-argument form of open. It's got a lot of advantages over the old two-argument form you're using. You should also use lexical filehandles rather than bareword filehandles. All of this has been possible since Perl 5.6, so the code you're writing is years out of date. Finally, you should always check that the open call worked, otherwise you will let your program continue when it is guaranteed to fail (if, say, permissions forbid you from opening a file to save your output to). Anyhow, the longer form would look like this:
    Code:
    open my $out_fh, '>', $filename
      or die "Problem opening $filename: $!";

Last edited by Telemachos; 10-17-2009 at 10:37 AM.
 
Old 10-17-2009, 10:26 AM   #4
bartonski
Member
 
Registered: Jul 2006
Location: Louisville, KY
Distribution: Fedora 12, Slackware, Debian, Ubuntu Karmic, FreeBSD 7.1
Posts: 443
Blog Entries: 1

Rep: Reputation: 47
Quote:
Originally Posted by Telemachos View Post
Some tips and thoughts:
  • If you need to create a group of filenames such as 'filename001.txt, filename002.txt' etc., there are easier, cleaner to read ways to do that. Here's one thought:
    Code:
    my @out_handles = map { $_ = 'filename00' . $_ . '.txt' } (0..9);
I like the use of 'map' there, I would also suggest using sprintf for the filename:

Code:
my @out_handles = map { $_ = sprintf("filename%03d.txt", $_) } (0..9);
This will continue to work when you have more than 10 files.

By the way, thanks for the tip about lexical filehandles. Apparently, I've been writing code that's years out of date ;-). I knew that the lexical filehandles were there, I just didn't realize how out of fashion bareword filehandles were...
 
Old 10-17-2009, 10:56 AM   #5
Telemachos
Member
 
Registered: May 2007
Distribution: Debian
Posts: 754

Rep: Reputation: 60
Quote:
Originally Posted by bartonski View Post
I like the use of 'map' there, I would also suggest using sprintf for the filename:

Code:
my @out_handles = map { $_ = sprintf("filename%03d.txt", $_) } (0..9);
This will continue to work when you have more than 10 files.
It's a very good improvement: my original idea was too close to the exact request (filename00 plus 0-9), and was more brittle. Thanks.

Quote:
By the way, thanks for the tip about lexical filehandles. Apparently, I've been writing code that's years out of date ;-). I knew that the lexical filehandles were there, I just didn't realize how out of fashion bareword filehandles were...
Yeah, and I apologize if I seemed overly dogmatic about it. I've only been programming in Perl for a relatively short time (roughly two years), and the badness of bareword filehandles has been very much beat into me. I can say that it really does make it much easier to deal with filehandles in larger programs, especially if you want to pass filehandles easily back and forth from subroutines.

(Also, just for what it's worth, I was really talking to the OP, who I thought was new to Perl. What I really meant to be saying was, "You're just learning Perl, so why not use more modern techniques.")

Last edited by Telemachos; 10-17-2009 at 10:59 AM.
 
Old 10-17-2009, 04:57 PM   #6
bartonski
Member
 
Registered: Jul 2006
Location: Louisville, KY
Distribution: Fedora 12, Slackware, Debian, Ubuntu Karmic, FreeBSD 7.1
Posts: 443
Blog Entries: 1

Rep: Reputation: 47
Quote:
Originally Posted by Telemachos View Post
Yeah, and I apologize if I seemed overly dogmatic about it. I've only been programming in Perl for a relatively short time (roughly two years), and the badness of bareword filehandles has been very much beat into me. I can say that it really does make it much easier to deal with filehandles in larger programs, especially if you want to pass filehandles easily back and forth from subroutines.
I support legacy code for a living, I have no problem with dogmatism in the face of un-maintainable code. I'll take all of the advantages that I can get.
 
Old 10-18-2009, 05:15 AM   #7
bigearsbilly
Senior Member
 
Registered: Mar 2004
Location: england
Distribution: NetBSD, Void, Debian, Mint, Ubuntu, Puppy, Raspbian
Posts: 3,487

Rep: Reputation: 233Reputation: 233Reputation: 233
you are making life very difficult for yourself.
perl supports this functionality anyway.
Code:
$x = "file000";
$x++;  # $x = file001
Code:
billy@foghorn:~$ perl -e  '$x='file000'; print $x++, "\n" foreach (1..10)'
file000
file001
file002
file003
file004
file005
file006
file007
file008
file009

Last edited by bigearsbilly; 10-18-2009 at 05:16 AM.
 
Old 10-18-2009, 06:18 AM   #8
syg00
LQ Veteran
 
Registered: Aug 2003
Location: Australia
Distribution: Lots ...
Posts: 19,098

Rep: Reputation: 3326Reputation: 3326Reputation: 3326Reputation: 3326Reputation: 3326Reputation: 3326Reputation: 3326Reputation: 3326Reputation: 3326Reputation: 3326Reputation: 3326
Every time I see a perl thread answered by billy I drop in - always learn summit ...
Cheers mate.
 
Old 10-18-2009, 07:30 AM   #9
bigearsbilly
Senior Member
 
Registered: Mar 2004
Location: england
Distribution: NetBSD, Void, Debian, Mint, Ubuntu, Puppy, Raspbian
Posts: 3,487

Rep: Reputation: 233Reputation: 233Reputation: 233
cheers!
nice to be appreciated!

shame all the employers I send my CV to don't agree.
bloody credit crunch.
 
Old 10-18-2009, 07:52 AM   #10
Telemachos
Member
 
Registered: May 2007
Distribution: Debian
Posts: 754

Rep: Reputation: 60
Quote:
Originally Posted by bigearsbilly View Post
you are making life very difficult for yourself.
perl supports this functionality anyway.
Code:
$x = "file000";
$x++;  # $x = file001
Code:
billy@foghorn:~$ perl -e  '$x='file000'; print $x++, "\n" foreach (1..10)'
file000
file001
file002
file003
file004
file005
file006
file007
file008
file009
At which point we still need to tack back on '.txt' for the OP's desired result.

Incrementing what Perl sees as a number is great, but it can sometimes turn DWIM (do what I mean) into WTF (translate yourself ):
Code:
telemachus ~ $ perl -e '$x = "filename000.txt"; print $x++, "\n" for (1..10);'
filename000.txt
1
2
3
4
5
6
7
8
9
 
Old 10-18-2009, 07:59 AM   #11
syg00
LQ Veteran
 
Registered: Aug 2003
Location: Australia
Distribution: Lots ...
Posts: 19,098

Rep: Reputation: 3326Reputation: 3326Reputation: 3326Reputation: 3326Reputation: 3326Reputation: 3326Reputation: 3326Reputation: 3326Reputation: 3326Reputation: 3326Reputation: 3326
Code:
perl -e '$x = 'filename000'; print $x++ . ".txt" "\n" for (1..10);'
???

Last edited by syg00; 10-18-2009 at 08:01 AM.
 
Old 10-18-2009, 07:59 AM   #12
bigearsbilly
Senior Member
 
Registered: Mar 2004
Location: england
Distribution: NetBSD, Void, Debian, Mint, Ubuntu, Puppy, Raspbian
Posts: 3,487

Rep: Reputation: 233Reputation: 233Reputation: 233
it's easy innit

Code:
$x = "file000";
$name = $x++ . ".txt";
doh! syg00 got there first!

well, it's a hint towards the answer, you can't expect me to
do all the work!

Last edited by bigearsbilly; 10-18-2009 at 08:01 AM.
 
Old 10-18-2009, 09:09 AM   #13
Telemachos
Member
 
Registered: May 2007
Distribution: Debian
Posts: 754

Rep: Reputation: 60
Quote:
Originally Posted by bigearsbilly View Post
it's easy innit

Code:
$x = "file000";
$name = $x++ . ".txt";
doh! syg00 got there first!

well, it's a hint towards the answer, you can't expect me to
do all the work!
No worries: I'm happy to do my own work. I wasn't asking for how to fix anything. I was just pointing out that your solution was incomplete.

Once we've moved to the new versions, I don't see how they're any easier than using map.
 
Old 10-18-2009, 09:11 AM   #14
Telemachos
Member
 
Registered: May 2007
Distribution: Debian
Posts: 754

Rep: Reputation: 60
Quote:
Originally Posted by syg00 View Post
Code:
perl -e '$x = 'filename000'; print $x++ . ".txt" "\n" for (1..10);'
???
??? indeed - did you even try to run that?

Code:
telemachus ~ $ perl -e '$x = 'filename000'; print $x++ . ".txt" "\n" for (1..10);'
String found where operator expected at -e line 1, near "".txt" "\n""
	(Missing operator before  "\n"?)
syntax error at -e line 1, near "".txt" "\n""
Execution of -e aborted due to compilation errors.
And, please, don't help me by adding the comma or moving \n into the .txt bit. As I said to Billy, I wasn't confused about how to do any of this in Perl. His answer didn't match what the OP asked for.
 
Old 10-18-2009, 11:44 AM   #15
bartonski
Member
 
Registered: Jul 2006
Location: Louisville, KY
Distribution: Fedora 12, Slackware, Debian, Ubuntu Karmic, FreeBSD 7.1
Posts: 443
Blog Entries: 1

Rep: Reputation: 47
Quote:
Originally Posted by bigearsbilly View Post
you are making life very difficult for yourself.
perl supports this functionality anyway.
Code:
$x = "file000";
$x++;  # $x = file001
very nice, and it works past 10 as well:

Code:
$ perl -e  '$x='file000'; print $x++, "\n" foreach (1..11)'
file000
file001
file002
file003
file004
file005
file006
file007
file008
file009
file010
definitely one to add to the bag o' tricks.
 
  


Reply


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
while loop creates a problem for a file opened in append mode for writing in PERL gaynut Programming 2 07-28-2008 07:26 PM
Perl eternal loop problem x_terminat_or_3 Programming 4 08-01-2007 02:12 AM
perl loop jazman Programming 3 07-05-2006 10:31 AM
Need help with perl loop! morbid_ru Programming 1 02-24-2004 01:14 PM
Need help with perl loop! morbid_ru Programming 2 02-17-2004 05:15 AM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 01:16 AM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration