Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Chriss Miller on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

foreach loop not working ?

Status
Not open for further replies.

abovebrd

IS-IT--Management
May 9, 2000
690
US
#!/usr/bin/perl

$var=`cal`;
@days=split(/\s+/, $var);

$removed=shift(@days);
$month=shift(@days);
$year=shift(@days);
$removed3=shift(@days);
$removed4=shift(@days);
$removed5=shift(@days);
$removed6=shift(@days);
$removed7=shift(@days);
$removed8=shift(@days);
$removed9=shift(@days);

foreach $day (@days) {
open(DATA, ">> /cgi-bin/cgi-date/$month$day-$year");
print DATA "$month , $date , $year\n";
close(DATA);
}

Can someone tell me why my foreach loop is not working? Or any ideas on how to make it work.
-Danny
techie@snoboarder.net






 
As long as @days has elements in it, the loop should work just fine. My concern is that you wrote:

print DATA "$month , $date , $year\n";

rather than:

print DATA "$month , $day , $year\n";

which seems odd since I don't see the $date variable anywhere.
Just to help debug, and see whether your loop is the problem, or rather the contents of the loop:

put a ' print "loop...\n"; ' in side the loop somewhere. That way everytime it loops we'll see that it did so.

Is your intent to create an individual file for each day of the month (i.e. cgi-bin/cgi-date/1225-2001) and then write a string in that file (i.e. 12, 25, 2001) ?

Becuase that what it looks like you are doing.

Tip: it looks like you are removing some values from the @days array, possibly just to get rid of them. In case you didn't plan on using them later, you could just get rid of the next, oh say, 7 elements by doing this:

shift(@days) x 7;

You don't have to assign the return value to a variable if you don't want to. shift() will still remove values.

Hope this helps.

--Jim
 
Jim,

Thanks for the tip "shift(@days) x 7;"

I'll try it out.

As far as $day and $date, that was a typo on my part. Both should have been $date. It appears the foreach loop did for after all. It created a text file using the @days elements

Question: How would I create a test to see if a file exsists. If it does the program moves on to the next loop and if if it does not exsist it creates the file using
open(data)

Thanks in advance.

I'm new to the wonderful world of perl.
-Danny
techie@snoboarder.net






 
Have a look at the perlfunc manpage for details of the list of tests for file status such as -e for "file exists". They are actually all at the top of the manpage.

Another point;
If you had written "#!/usr/bin/perl -w" (without the quotes) at the top of your script, the -w switch would have turned on warnings and informed you of your typo in the foreach loop.
 
In response to:
[tt]
Question: How would I create a test to see if a file exsists. If it does the program moves on to the next loop and if if it does not exsist it creates the file using
open(data)[/tt]


There is a real simple way to accomplish this:

Just inside the for loop:
[tt]
next if -e "/cgi-bin/cgi-date/$month$day-$year";
[/tt]


this will do exactly what you described. It is using the 'file test operator' which greadey described above.

Hope it works for ya!

--Jim
 
Jim,

next if -e "/cgi-bin/cgi-date/$month$day-$year";

This statement only checks to see if the file exsists ! What I need is to check if the exsists,
if it does exsist exit the foreach loop
if it does not exsist continue with the foreach loop.

Please correct of me I am wrong.

Thanks
-Danny
techie@snoboarder.net






 
In response to:
[tt]
next if -e "/cgi-bin/cgi-date/$month$day-$year";

This statement only checks to see if the file exsists ! What I need is to check if the exsists,
if it does exsist exit the foreach loop
if it does not exsist continue with the foreach loop.

Please correct of me I am wrong.
[/tt]


Dear Danny. You are wrong. But that's ok.

In any given loop, the next statement will cause perl to immediately skip to the next iteration of that loop without executing any statements that may exist inside of the loop, but after the next statement.

[tt]
for($x = 1; $x < 11; $x++){
print &quot;Before the next statement.&quot;;
next;
print &quot;After the next statement.&quot;;
}
[/tt]

This code will never print &quot;After the next statement.&quot; becuase the next statement forces it to immediately skip to the next iteration of that loop. It produces 10 x &quot;Before the next statement.&quot;

The advice of my previous post was to insert the 'test' just after the loop initiation. Thus the loop would begin and the first line inside the loop would check to see if such a file existed, and if so skip to the next iteration. This would allow the processing of each element in your @days array, processing only the elements whose corresponding files DID NOT already exist.

This is what you descibed as needing. No where in your description did you describe 'exiting the loop prematurely' based on whether the file exists. You said:

If it
(the file) does (exist) the program moves on to the next loop

If you wish to exit the loop without processing any subsequent array elements, then use Barbie's advice.

Sorry if I misunderstood the original question.

--Jim
 
Jim,

Thanks for spelling that out for me.


-Danny
techie@snoboarder.net






 
Jim,
Thanks for the awesome help. You are a perl guru.

The above script works fabulous. I have picked up a few pointers along the way. I just can't seem to get the file test to work.

last if -e &quot;cgi-date/$month$date-$year&quot;;

I added to the foreach loop. But it didn't seem to work. I can only asume that I added it in the wrong place.
Thanks for all the help, I'm throwing in the towel (at least for now)
perl -1 Danny -0

foreach my $date (@_) {

$mylink = &quot;/cgi-bin/date/$month$date-$year&quot;; # Path to date directory
$str .= &quot;<TD align='center'BGCOLOR=#C6EFF7><A HREF='$mylink'>$date</A></TD>&quot;;
open(DATA, &quot;> ./date/$month$date-$year&quot;);
print DATA &quot;<HTML><HEAD><TITLE>Calendar Event $month$date-$year</TITLE></HEAD><BODY>\n&quot;;
print DATA &quot;<H1>Daily Events for $month $date ,$year</H1>\n&quot;;
print DATA &quot;\n&quot;;
print DATA &quot;\n&quot;;
print DATA &quot;<A HREF=\&quot;../../index.shtml\&quot;><img src=\&quot;../../images/bug.jpg\&quot; BORDER=0></A>\n&quot;;
print DATA &quot;</BODY></HTML>\n&quot;;
close(DATA);
last if -e &quot;cgi-date/$month$date-$year&quot;;
}
return $str;

}

-Danny
techie@snoboarder.net






 
Danny,

Thanks alot for the praise. It's cool to know that you appreciate it so much. As far as being a perl guru, I still have many things to learn. But that's the fun part anyways.

OK, your script has several oddities that hit me right off the bat, I'll point them out and then post the entire script with my corrections based on my suspicions of what was going wrong.

Your SCRIPT:
[tt]
01: foreach my $date (@_) {
02: $mylink = &quot;/cgi-bin/date/$month$date-$year&quot;;
#Path to date directory
03: $str .= &quot;<TD align='center'BGCOLOR=#C6EFF7>
<A HREF='$mylink'>$date</A></TD>&quot;;
04: open(DATA, &quot;> ./date/$month$date-$year&quot;);
05: print DATA &quot;<HTML><HEAD><TITLE>Calendar Event
$month$date-$year</TITLE></HEAD><BODY>\n&quot;;
06: print DATA &quot;<H1>Daily Events for $month
$date ,$year</H1>\n&quot;;
07: print DATA &quot;\n&quot;;
08: print DATA &quot;\n&quot;;
09: print DATA &quot;<A HREF=\&quot;../../index.shtml\&quot;><img
src=\&quot;../../images/bug.jpg\&quot; BORDER=0></A>\n&quot;;
10: print DATA &quot;</BODY></HTML>\n&quot;;
11: close(DATA);
12: last if -e &quot;cgi-date/$month$date-$year&quot;;
13: }
14: return $str;
15: }
[/tt]



Oddity 1: You specify a file path in lines 2 and 12. It seems to me that these paths should point to the same file.
Also, on line 12, you may need a &quot;/&quot; or a &quot;../&quot; in front of that &quot;cgi-date&quot; directory. Depends on what directory your script is running from, but that's just a suspicion.

Oddity 2: Your last statement on line 12 will exit the loop completely and won't process any more array elements after that. Are you sure this is what you want? Also it's odd that it's at the end of the loop block. Normally a line like this would be the first statement (or close to it) in the loop. (I still think it should be a next statement instead of alast.

OK, here is what I think the sub should look like:

[tt]

foreach my $date (@_) {
$mylink = &quot;/cgi-bin/date/$month$date-$year&quot;;
next if -e $mylink;

# I'll assume this is the correct directory.
$str .= &quot;<TD align='center'BGCOLOR=#C6EFF7><A HREF='$mylink'>$date</A></TD>&quot;;
open(DATA, &quot;> $mylink&quot;);
print DATA &quot;<HTML><HEAD><TITLE>Calendar Event $month$date-$year</TITLE></HEAD><BODY>\n&quot;;
print DATA &quot;<H1>Daily Events for $month $date ,$year</H1>\n&quot;;
print DATA &quot;\n&quot;;
print DATA &quot;\n&quot;;
print DATA &quot;<A HREF=\&quot;../../index.shtml\&quot;><img src=\&quot;../../images/bug.jpg\&quot; BORDER=0></A>\n&quot;;
print DATA &quot;</BODY></HTML>\n&quot;;
close(DATA);
}
return $str;

}
[/tt]


I could be wrong, but give it a shot. This will create the files (from you array elements) that don't exist, and will skip over them if they do exist.

Toasty.

Hope this helps.

--Jim
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top