Switching with case in perl ?

L

lerameur

Hello,

I used the switching command CASE in c++
Is there such a thing in perl.? I did not find the command from
googling with perl.

the reason for this is I am trying to increment a time. Maybe there is
a way around it. Here is the part of the program I have:
Goal: there are many log files per hour. The program should put it to
one file, starting from the user input date. The problem is getting
the roller over date.

$year2= 07; #type in the year
$month2= 09; #type in the month
$day2= 05; #type in the day
$hours2 = 04; #type in the hour

$logTime = $year$month$day$hours; # date to begin search

$minutes_count = 0; #Put to zero every time it will go throw the loop
to gather all log files within that hour
if($minutes_count<10) {
$minutes_count="0$minutes_count";
} else {
$minutes_count=$minutes_count; #Calculate
Minutes_count for double digit
}
$logTimeIncrement = $logTime$minutes_count"*";
while ($minutes_count != 60){ # This loop goes through every minute
for that our and append the new found log to the main hour log
if ($logTimeIncrement == true){
open (log_$logTime, >>log_$logTime) ||
die ("Cannot open input file $logTimeIncrement \n") ; # this file is
the accumulator file
open (File, >>$logTimeIncrement) ||
die ("Cannot open input file $logTimeIncrement \n") ;
$doc1 = <log_$logTime>;
$doc2 = <File>;

while ($doc1 ne " " || $doc2 ne " "){
if ($doc1 ne " ") {
print ($doc1);
$doc1 = <log_$logTime>>;
}
if ($doc2 ne " "){
print ($doc2);
$doc2 = <File>;
}
} #end of while loop

}
$minutes_count++;

if($minutes_count<10) {
$minutes_count="0$minutes_count";
} else {
$minutes_count=$minutes_count;

}
# Checking the roller over dates
if ($minutes_count ==60){
$hours2++;
$minutes_count=0;
}

if ($hours2==24){
$day2++;
$hours2=0;
}

I stopped here since I decided to look for case equivalent.
 
P

Paul Lalli

I used the switching command CASE in c++
Is there such a thing in perl.?

Yes. perldoc Switch.
I did not find the command from googling with perl.

Google should be your last resort. The built in documentation should
be your first.

$ perldoc -q switch
Found in /opt2/Perl5_8_4/lib/perl5/5.8.4/pod/perlfaq7.pod
How do I create a switch or case statement?

the reason for this is I am trying to increment a time. Maybe
there is a way around it. Here is the part of the program I
have:
Goal: there are many log files per hour. The program should put
it to one file, starting from the user input date. The problem is
getting the roller over date.

$year2= 07; #type in the year
$month2= 09; #type in the month
$day2= 05; #type in the day
$hours2 = 04; #type in the hour

That can't be your real code. You're using octal numbers, and 9 isn't
a valid octal digit. This causes a syntax error. Please copy and
paste your real code from now on.
$logTime = $year$month$day$hours; # date to begin search

More syntax errors.
$minutes_count = 0; #Put to zero every time it will go throw the loop
to gather all log files within that hour
if($minutes_count<10) {
$minutes_count="0$minutes_count";
} else {
$minutes_count=$minutes_count; #Calculate
Minutes_count for double digit
}

This makes no sense. At the time of this if statement, $minutes_count
will always be zero. So why don't you just start it off at "00" to
begin with?
$logTimeIncrement = $logTime$minutes_count"*";

More syntax errors.
while ($minutes_count != 60){ # This loop goes through every minute
for that our and append the new found log to the main hour log
if ($logTimeIncrement == true){

Not a syntax error, but definitely not what you want. The bareword
true will either be seen as a function call true() or as the string
"true". The string "true" in numeric context is 0, which is false.

I'm done looking through this code. If you want to increment time
values, you should be using the built in time manipulation functions:

use POSIX 'strftime';
my $year = 7;
my $month = 9;
my $day = 5;
my $hours = 4;
for my $minute (45..70) {
print strftime("%H:%M %m/%d/%Y", 0, $minute, $hours, $day, $month -
1, $year + 100), "\n"
}


Output:
04:45 09/05/2007
04:46 09/05/2007
04:47 09/05/2007
04:48 09/05/2007
04:49 09/05/2007
04:50 09/05/2007
04:51 09/05/2007
04:52 09/05/2007
04:53 09/05/2007
04:54 09/05/2007
04:55 09/05/2007
04:56 09/05/2007
04:57 09/05/2007
04:58 09/05/2007
04:59 09/05/2007
05:00 09/05/2007
05:01 09/05/2007
05:02 09/05/2007
05:03 09/05/2007
05:04 09/05/2007
05:05 09/05/2007
05:06 09/05/2007
05:07 09/05/2007
05:08 09/05/2007
05:09 09/05/2007
05:10 09/05/2007


Paul Lalli
 
B

Ben Morrow

Quoth Paul Lalli said:
Yes. perldoc Switch.

Please don't recommend Switch.pm to people. It has serious bugs (due to
being implemented as source filter); e.g.

#!/usr/bin/perl

use Switch;

sub foo ($) {
switch ($_[0]) {
case 1 { print "OK\n" }
}
}

foo(1);

__END__

with Switch-2.13 (the latest version) fails with

Number found where operator expected at sw line 7, near "case 1"
(Do you need to predeclare case?)
syntax error at sw line 6, near ") {"
syntax error at sw line 8, near "}"
Execution of sw aborted due to compilation errors.

as Switch (or rather Text::Balanced) confuses '($)' with '$)' and loses
the close bracket on the prototype. There have been lots of other bugs
like this in the past: some have been fixed, but there are undoubtedly
many more left. The faq has been updated on faq.perl.org to reflect this
fact; unfortuately, there's no way to update all the copies of perlfaq7
installed on people's machines :).

If you really really really need a switch statement, wait for 5.10
(RealSoonNow :) ) which has one in the form of a Perl6ish given/when;
otherwise, stick to the other solutions in the FAQ.

<lots of good sense snipped>

Ben
 
L

lerameur

lerameurwrote:

Yarg! Haven't you ever used sprintf?


$logTime = sprintf "%04d/%02d/%02d_%02d:%02d",
$year, $month, $day, $hour, $minute;

And are you aware thatPerlhas the ability to increment strings?

perl-le '$n="00";$s="cw";print $n++," ",$s++ for (0..12)'

That comes into play if you have
$value = "00";
instead of
$value = 0;
and then use $value++ or ++$value.

-Joe

hello again, thanks for the function, it works good.
I am new to perl so i dont know all the internal functions.
I get the following error from this line , can you tell me why:

for my $minute (0..59) {
my $logtime = strftime("%y%m%d%H%M", 0, $minute, $hours, $day, $month
-1, $year + 100), "\n"; #line 20
print $logtime,"\n";
}

error: Useless use of constant in void context at line 20.

k
 
J

John W. Krahn

lerameur said:
hello again, thanks for the function, it works good.
I am new to perl so i dont know all the internal functions.
I get the following error from this line , can you tell me why:

for my $minute (0..59) {
my $logtime = strftime("%y%m%d%H%M", 0, $minute, $hours, $day, $month
-1, $year + 100), "\n"; #line 20
print $logtime,"\n";
}

error: Useless use of constant in void context at line 20.

The ', "\n"' at the end of line 20 is the problem. You are assigning "\n" to
$logtime because of the comma opertor.



John
 
P

Paul Lalli

The ', "\n"' at the end of line 20 is the problem. You are
assigning "\n" to $logtime because of the comma opertor.

No he's not. = has a higher precedence than ,. He's assigning the
results of strftime(...) to $logtime, and then that assignment and the
"\n" are both evaluated by the , operator.

$ perl -MO=Deparse,-p -e'my $x = foo(), 5;'
((my $x = foo()), '???');
-e syntax OK


Regardless, you are correct as to what the problem is, just not what
the end result is.

To the OP: Don't blindly copy my code and then modify it without even
bothering to understand it. When I posted that code, I was printing
the strftime() and then the "\n" in the same statement. In your
modification, you changed the print to a variable assignment, and then
tried to print the variable and another newline.

Paul Lalli
 
L

lerameur

No he's not. = has a higher precedence than ,. He's assigning the
results of strftime(...) to $logtime, and then that assignment and the
"\n" are both evaluated by the , operator.

$perl-MO=Deparse,-p -e'my $x = foo(), 5;'
((my $x = foo()), '???');
-e syntax OK

Regardless, you are correct as to what the problem is, just not what
the end result is.

To the OP: Don't blindly copy my code and then modify it without even
bothering to understand it. When I posted that code, I was printing
the strftime() and then the "\n" in the same statement. In your
modification, you changed the print to a variable assignment, and then
tried to print the variable and another newline.

Paul Lalli

Well I thought I did understand...

here the whole code for that part:

for my $minute (0..59) {
my $logtime = strftime("%y%m%d%H%M", 0, $minute, $hours, $day, $month
-1, $year + 100) ;
#open each traffic log files and append them to one files
open (FILE_1,"</*$year$month$day$hours$minute*/"); #............
#Line 23
foreach $line (<FILE_1>) {
if ($line =~ m/david/) {
open (FILE, ">>$year$month$day$hours.txt");
@items = split(",",$line);
print FILE $items[0], ",", $items[1], ",", $items[2],",",
$items[2], ";" . "\n";
close(FILE);
}
}
} #closing for my minute loop
close (FILE_1);

here is my full code. I get the error: readline() on closed
filehandle FILE_1 at C:\Perl\eg\ccc.pl line 23.
I want to create one log file out of 5 log files that are created
every hour. I am not sure how to use the '*' the log file is in the
format log_$year$month$day$hours$minute_.txt

k
 
P

Paul Lalli

open (FILE_1,"</*$year$month$day$hours$minute*/");

You're trying to open a file in the root directory that starts with an
asterisk and that ends with an asterisk and a slash. I'm willing to
bet no such file exists. Of course, Perl would tell you that if you
bothered asking. You're not bothering - you're not checking the
return value of open() to see if it succeeded.

open my $fh, '<', "filename" or die "Could not open file: $!";

If you're attempting to open any file that matches that pattern, you
need to use the glob() function to get a list of all matching files:

my @files = glob("*$year$month$day$hours$minute*");
for my $file (@files) {
open my $fh, '<', $file or die "Could not open $file: $!";
while (my $line = <$fh>) {
#...
}
}

Paul Lalli
 
B

Ben Morrow

Not an error: a warning. The distinction is important.
Maybe you have format or parameters in reverse order :)

You can write this

my $logtime = strftime("%y%m%d%H%M\n", $year + 100, $month -1, $day, $hours,
$minute);

I think you're confusing strftime with sprintf. The former does not
expect its parameters in the order they are used, it expects a whole
broken-out 'struct tm' (second, minute, hour, day, month, year in that
order). See perldoc POSIX.
my $logtime = strftime("%y%m%d%H%M", $year + 100, $month -1, $day, $hours,
$minute) . "\n";
# use dot for concate instead comma operator

The comma operator never concatenates... the mystery is why the OP
thought it did :).

Ben
 
J

John W. Krahn

Paul said:
No he's not. = has a higher precedence than ,. He's assigning the
results of strftime(...) to $logtime, and then that assignment and the
"\n" are both evaluated by the , operator.

Yes, thank you. I realised my mistake a while after posting but then I wasn't
near the computer to correct it.


:)

John
 
L

lerameur

Paul I used your glob function, I think this is sweet function.
I tried using it with no success, I modified a little bit and still no
success. Basically it is not creating the output file, and gives me an
error when I try closing the file I am using to read.
here is the original:

my @files = glob("*$year$month$day$hours$minute*"); #looking at all
files in the directory
for my $file (@files) {
open my $fh, '<', $file or die "Could not open $file: $!";
while (my $line = <$fh>) {
if ($line =~ m/beth/) {
open (FILE, ">>Loog_rr.txt"); #this line is not creating the
file
@items = split(",",$line);
print FILE $items[0], ",", $items[1], ",", $items[2],",",
$items[3], ";" . "\n";
close(FILE);
}
}
}
}#closing for my minute loop
#close ($fh);



*******************************
and here is the modified version

while ($filename = glob("*$year$month$day$hours$minute*") ){ #looking
at all files in the directory
open (wordlisting1, $filename) or die "Could not open wordlisting:
";
while ($filename ne " " ) {
if ($line =~ m/beth/) {
open (FILE, ">>Loooooog_rr.txt");
@items = split(",",$line);
print FILE $items[0], ",", $items[1], ",", $items[2],",",
$items[3], ";" . "\n";
close(FILE)|| die "couldn't close FILE: $!";;
}
}
}
}#closing for my minute loop
close (wordlisting1) || die "couldn't close wordlisting: ";
 
P

Paul Lalli

Paul I used your glob function, I think this is sweet function.
I tried using it with no success, I modified a little bit and still no
success. Basically it is not creating the output file, and gives me an
error when I try closing the file I am using to read.

You are *still* not checking open for errors, you are *still* not
including $! in the error message for the close.

If you refuse to ask Perl for help, why should any actual human beings
continue to help you?

Paul Lalli
 
R

Ron Bergin

Paul I used your glob function, I think this is sweet function.
I tried using it with no success, I modified a little bit and still no
success. Basically it is not creating the output file, and gives me an
error when I try closing the file I am using to read.
here is the original:

my @files = glob("*$year$month$day$hours$minute*"); #looking at all
files in the directory
for my $file (@files) {
open my $fh, '<', $file or die "Could not open $file: $!";
while (my $line = <$fh>) {
if ($line =~ m/beth/) {
open (FILE, ">>Loog_rr.txt"); #this line is not creating the
file
@items = split(",",$line);
print FILE $items[0], ",", $items[1], ",", $items[2],",",
$items[3], ";" . "\n";
close(FILE);
}
}
}
}#closing for my minute loop
#close ($fh);

*******************************
and here is the modified version

while ($filename = glob("*$year$month$day$hours$minute*") ){ #looking
at all files in the directory
open (wordlisting1, $filename) or die "Could not open wordlisting:
";
while ($filename ne " " ) {
if ($line =~ m/beth/) {
open (FILE, ">>Loooooog_rr.txt");
@items = split(",",$line);
print FILE $items[0], ",", $items[1], ",", $items[2],",",
$items[3], ";" . "\n";
close(FILE)|| die "couldn't close FILE: $!";;
}
}
}
}#closing for my minute loop
close (wordlisting1) || die "couldn't close wordlisting: ";

It doesn't appear that you're using the strict or warnings pragmas.
It would help if you ask Perl why it can't open the Loog_rr.txt file.
It would also be better to put that open call prior to the glob.
You also need to make your code easier to read/maintain by reducing
the amount of indentation.

open(my $out_file, '>>', 'Loog_rr.txt') or die "Can't open Loog_rr.txt
$!";

while (my $filename = glob("*$year$month$day$hours$minute*") ){
open($wordlisting1, '<', $filename) or die "Could not open
wordlisting: $!";
while (my $line = <$wordlisting1> ) {
if ($line =~ m/beth/) {
@items = (split(",",$line))[0..3];
print $out_file join(',', @items) , ";\n";
}
}
close($wordlisting1) || die "couldn't close wordlisting: $!";
}
close $out_file or die "Can't close out_file $!";
 
L

lerameur

You are *still* not checking open for errors, you are *still* not
including $! in the error message for the close.

If you refuse to askPerlfor help, why should any actual human beings
continue to help you?

Paul Lalli

I added them for the close and missed one for the open.
i added -or die "Could not open file: $!"; -

I am not getting any error on opening files though.

k
 
L

lerameur

I added them for the close and missed one for the open.
i added -or die "Could not open file: $!"; -

I am not getting any error on opening files though.

k

HI,

the loop is working but keeps on looping, Once the outer loop finds
the file, it gets the logs to the output file and keep repeating
extracting from the same log file. had to do a control C cause the
output file is growing huge.
k
 
B

Ben Morrow

Quoth Ron Bergin said:
It doesn't appear that you're using the strict or warnings pragmas.
It would help if you ask Perl why it can't open the Loog_rr.txt file.
It would also be better to put that open call prior to the glob.
You also need to make your code easier to read/maintain by reducing
the amount of indentation.

open(my $out_file, '>>', 'Loog_rr.txt') or die "Can't open Loog_rr.txt
$!";

while (my $filename = glob("*$year$month$day$hours$minute*") ){
open($wordlisting1, '<', $filename) or die "Could not open
wordlisting: $!";
while (my $line = <$wordlisting1> ) {
if ($line =~ m/beth/) {
@items = (split(",",$line))[0..3];

You mention strictures above, but @items is not declared anywhere.

Except for the very special case of ' ', the first argument to split is
a regex. You should write it as a regex so people don't misread it:

my @items = ( split( /,/, $line ) )[0..3];
print $out_file join(',', @items) , ";\n";

This can be made cleaner by using Perl's print-control variables: put

local ($,, $\) = (',', ';\n');

at the top of the loop and then simply

print $out_file @items;
}
}
close($wordlisting1) || die "couldn't close wordlisting: $!";

You want to be consistent about whether you use || or 'or' to check for
errors. Personally I'd always use 'or'; but then I'd always omit the
parens on open as well.

There's little point in checking for errors on close if you haven't
checked for errors as you read. What errors could occur at this point
that you care about?
}
close $out_file or die "Can't close out_file $!";

Again, the point of checking for errors when you close a file you were
writing to is to ensure all the data got written successfully: if you
care, you should be checking print succeeded as well.

Ben
 
L

lerameur

Hi,
I found the problem but have not been able to fix it.
th e output is good, but prints twice
I have two loop, with each its own increment. The while loop with the
glob function just hangs. I use an increment in that loop for minute2,
but minute2 also get incremented by the outer loop: Is there some sort
of exit I get put in my inner loop.
Also I tried using this:
my $filename = glob("*$year2$month2$day2$hours2$minute2*") ;
but I had so many errors I did not bother.

here is the program. I think this is more of logic question.:

for my $minute2 (0..59) {
my $logtime = strftime("%y%m%d%H%M", 0, $minute2, $hours2, $day2,
$month2 -1, $year2 + 100). "\n" ;
#open each traffic log files and append them to one files

open(my $out_file, '>>', '$logtime$timestamp.txt') or die "Can't open
Log.txt$!";

while (my $filename = glob("*$year2$month2$day2$hours2$minute2*") ){

open($wordlisting1, '<', $filename) or die "Could not open
wordlisting: $!";
while (my $line = <$wordlisting1> ) {
if ($line =~ m/beth/) {
my @items = (split(/,/,$line))[4,10,15,86];
print $out_file join(',', @items). "\n";
}
} print $minute2;
close($wordlisting1) or die "couldn't close wordlisting: $!";
}
close $out_file or die "Can't close out_file $!";
}#closing for my minute loop



k
 
L

lerameur

Hi,
I found the problem but have not been able to fix it.
th e output is good, but prints twice
I have two loop, with each its own increment. The while loop with the
glob function just hangs. I use an increment in that loop for minute2,
but minute2 also get incremented by the outer loop: Is there some sort
of exit I get put in my inner loop.
Also I tried using this:
my $filename = glob("*$year2$month2$day2$hours2$minute2*") ;
but I had so many errors I did not bother.

here is the program. I think this is more of logic question.:

for my $minute2 (0..59) {
my $logtime = strftime("%y%m%d%H%M", 0, $minute2, $hours2, $day2,
$month2 -1, $year2 + 100). "\n" ;
#open each traffic log files and append them to one files

open(my $out_file, '>>', '$logtime$timestamp.txt') or die "Can't open
Log.txt$!";

while (my $filename = glob("*$year2$month2$day2$hours2$minute2*") ){

open($wordlisting1, '<', $filename) or die "Could not open
wordlisting: $!";
while (my $line = <$wordlisting1> ) {
if ($line =~ m/beth/) {
my @items = (split(/,/,$line))[4,10,15,86];
print $out_file join(',', @items). "\n";
}
} print $minute2;
close($wordlisting1) or die "couldn't close wordlisting: $!";
}
close $out_file or die "Can't close out_file $!";
}#closing for my minute loop

k

I found the problem. Added this at the beginning:
for my $minute2 (00..59) {
if($minute2<10) {
$minute2="0$minute2";
} else {
$minute2=$minute2;
}

.....

k
 
A

Anno Siegel

[...]
I found the problem. Added this at the beginning:
for my $minute2 (00..59) {
if($minute2<10) {
$minute2="0$minute2";
} else {
$minute2=$minute2;
}

That can be achieved simpler using Perl's magical string increment:

for my $minute2 ( '00' .. '59' ) {
# ...

Anno
 
L

lerameur

[...]

I found the problem. Added this at the beginning:
for my $minute2 (00..59) {
if($minute2<10) {
$minute2="0$minute2";
} else {
$minute2=$minute2;
}

That can be achieved simpler usingPerl'smagical string increment:

for my $minute2 ( '00' .. '59' ) {
# ...

Anno

wow ok , thanks

I guess one more thing I did not see is the file name.
open(my $out_file, '>>$logtime$timestamp.txt') or die "Can't open
Log.txt$!";

The file name that is being created has the name $logtime
$timestamp.txt
it should the the time from the timestamp I created earlier.
I tried double quoting. what should I sue for the punctuation there.
Also tried using the same syntax of a simple open file command, that
uses double quote, and no success there either.

thanks
k
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,767
Messages
2,569,572
Members
45,045
Latest member
DRCM

Latest Threads

Top