On Dec 23, 2006, at 9:25 PM, Chris Charley wrote:
----- Original Message ----- From: "Kirk Wythers" <[EMAIL PROTECTED]>
Newsgroups: perl.beginners
To: "John W. Krahn" <[EMAIL PROTECTED]>
Cc: "Perl Beginners" <beginners@perl.org>
Sent: Saturday, December 23, 2006 1:32 PM
Subject: Re: run script on multiple files
Thanks or the reply John. I have a couple of questions inline.
On Dec 22, 2006, at 10:53 PM, John W. Krahn wrote:
#! /usr/bin/perl -w
use strict;
use Date::Calc qw(Day_of_Year);
use DBI;
#MICIS climate data munger. Required input argument is the file to
process.
#Use > to redirect output to new file.
#Set the item delimiter to tabs instead of the default commas
and the line
The Output Field Separator ($,) has the default value of undef.
I guess I'm too new at this. I don't understand your point.
Above, you said 'Set the item delimiter to tabs instead of the
default commas'
and John is saying that the default of $, is undef, not a comma.
[snip]
#Part 1. Loop through the 11 header lines to identify the
station id.
#The 7th line contains the station ID, and has the format of
#STATION: SOME_STATION, STATE (Station ID: ######)
for(my $i=1;$i<=6;$i++) {
Your comment says eleven lines but your code says six?
A mistake on my part not updating the comments. The earlier file
format had 11 lines.
You need to correct this in John's code where it says:
if (1..11)
should then be
if (1..6)
[snip]
You are using the <> operator to read from the file(s) so this
*will* read all
the lines from all the files listed on the command line. The
only problem is
that you will not distinguish the headers from the second and
subsequent files
listed on the command line.
That will not do. I need to start fresh on each file. Just as if
I ran the program as:
./program.pl file1
./program.pl file2
./program.pl file3
ect....
And thats what John's solution does. In his code:
# At eof close the input filehandle to reset $.
if ( eof ) {
close ARGV;
next;
}
That 'resets' $. to 1 (beginning line of the next file) and the
'next' keyword
instructs your program to 'goto' the while (<>) statement above
thus not processing
any of the statements below it at the end of each file.
[snip]
This may work better for you:
#!/usr/bin/perl -w
use strict;
use Date::Calc qw(Day_of_Year);
use DBI;
my $dbh = DBI->connect( 'DBI:Pg:dbname=met_data;host=localhost',
'pguser',
'pguser' )
or die "Couldn't connect to PostgreSQL: $DBI::errstr
($DBI::err) \n";
my $sth = $dbh->prepare( 'INSERT INTO weather (station_id,
year, month, day,
doy, date, precip, tmin, tmax, snowfall, snowdepth, tmean) VALUES
(?,?,?,?,?,?,?,?,?,?,?,?)' );
my $station_id = '';
while ( <> ) {
# Part 1. Loop through the 11 header lines to identify the
station id.
# The station ID has the format of:
# STATION: SOME_STATION, STATE (Station ID: ######)
if ( 1 .. 11 ) {
$station_id = $1 if /\(Station ID:\s*(\S+)\)/;
Thi regular expression wants to match:
\( - a literal left parenthesis
Station ID: - then this text
\s* - 0 or more spaces
(\S+) - 1 or more non-space characters (enclosed in capturing
parentheses
whose value will be held in $1)
\) - a final literal right parenthesis
It seems that this is more flexable. ie not dependent upon a
certine number of header lines. Can you translate the f /\(Station
ID:\s*(\S+) \)/; part though?
next;
}
# At eof close the input filehandle to reset $.
if ( eof ) {
close ARGV;
next;
}
I think this is suppose to allow the script to jump to the next
file. Right?
Right
However, this script also reads the first file into the database,
then stops.
Don't know why - maybe someone else could say.
I think I see what is happening. John's script was crashing at the
end of the first file with an error that I saw earlier when writing
my script. There is a footer at the end of each file and as soon as
the script hits the footer junk, it gives:
Use of uninitialized value in concatenation (.) or string at ./
micis_final.pl line 38, <> line 37993.
Use of uninitialized value in concatenation (.) or string at ./
micis_final.pl line 38, <> line 37993.
In my script I solved this problem by telling the program to exit
when there is nothing in $year (essentially the first empty line
which always comes after the last line of data and before the
footer). Since Johns script was giving the same error, I added my two
bit solution. My guess is that I am telling the program to exit
before the the file handle closes and $ is reset.
I below is john's code with my addition. Any ideas how to get out of
each file when a blank line is hit, and still close the file handle
re-set $?
#!/usr/bin/perl -w
use strict;
use Date::Calc qw(Day_of_Year);
use DBI;
my $dbh = DBI->connect( 'DBI:Pg:dbname=met_data;host=localhost',
'pguser', 'pguser' )
or die "Couldn't connect to PostgreSQL: $DBI::errstr ($DBI::err)
\n";
my $sth = $dbh->prepare( 'INSERT INTO weather (station_id, year,
month, day, doy, date, precip, tmin, tmax, snowfall, snowdepth,
tmean) VALUES (?,?,?,?,?,?,?,?,?,?,?,?)' );
my $station_id = '';
while ( <> ) {
#Part 1. Loop through the header lines to identify the station id.
#The station ID has the format of:
#STATION: SOME_STATION, STATE (Station ID: ######)
if ( 1 .. 11 ) {
$station_id = $1 if /\(Station ID:\s*(\S+)\)/;
next;
}
#At eof close the input filehandle to reset $.
if ( eof ) {
close ARGV;
next;
}
#Part 2. Loop through the records and prepare SQL statement.
my ( $year, $month, $day, $precip, $tmin, $tmax, $snowfall,
$snowdepth, $tmean, $obstime, $datasource ) = split;
#Stop reading data at the end of the file, when $year is empty.
This
#gets you out of the datafile before the program chokes on the
footer.
exit unless $year;
#Initialize and concatenate date as YYYMMDD.
my $date = $year . $month . $day;
#Initialize and calculate day of the year (doy)
my $doy = Day_of_Year( $year, $month, $day );
#Switch T (trace) to 0.01 and M (missing) to -999
$precip = 0.01 if $precip eq 'T';
for ( $precip, $tmin, $tmax, $snowfall, $snowdepth, $tmean ) {
$_ = -999 if $_ eq 'M';
}
$sth->execute( $station_id, $year, $month, $day, $doy, $date,
$precip, $tmin, $tmax, $snowfall, $snowdepth, $tmean );
#print join( "\t", $station_id, $year, $month, $day, $doy,
$date, $precip, $tmin, $tmax, $snowfall, $snowdepth, $tmean ), "\n";
}
#$sth->finish();
# Disconntect from database
$dbh->disconnect();
__END__
--
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]
<http://learn.perl.org/> <http://learn.perl.org/first-response>