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 SkipVought on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

how to open a 2nd file and loop through the lines 1

Status
Not open for further replies.

mrimagepueblo

Programmer
Dec 15, 2003
52
0
0
US
I don't know if this is enough information on the code but I think this is the subroutine that is messing up. I'm basically opening a 2nd data file (test.txt) and trying to read each line and run the lookup based on the original data file for matching results. I get the first line of the test.txt file ok and it sends the expected email, but it doesn't get through the remaining lines in the test.txt file?
Does this code look right to do that?

open (KEYWORDFILE, "test.txt") || die "can't open keyword file\n";

while (<KEYWORDFILE>)
{
@lines = (<KEYWORDFILE>);
foreach $line (@lines)

{
chop ($line);
@notifyfields = split(/\|/,$_);
}
$form_data{'id9'}= $notifyfields[9];

close (KEYWORDFILE);
}
}


#######
the $form_data('id9'}=$notifyfields[9]; matches the 9th field in the original data file to the 9th field in the test.txt, which causes the program to email me the results

 
Are you trying to chop the line vs chomp the line? Also close (KEYWORDFILE) need to be outside the loop.
 

Try to put 'close (KEYWORDFILE)' outside the while loop.
 
I kind of thought the close was in the wrong place. I'll work a little on that since I got similiar recommendations. I've actually been moving it around but keep getting the same results. I'll keep trying.
Since the file is a unix text file. I thought chop was the way to go?
 
if ur are del the last character yes, chop is right way. If you removing the new line instance, then chomp is what does the trick. close (FH) needs to be outside the while loop for sure.

Also, print $notifyfields[9] inside the foreach loop, see what you get...Now print it outside the foreach loop and see what you get. :)
 
Maybe this is what you are trying to do:

Code:
open (KEYWORDFILE, "test.txt") || die "can't open keyword file\n";
@lines = <KEYWORDFILE>;
close (KEYWORDFILE);
foreach $line (@lines)
{
   chomp ($line);
   my @notifyfields = split(/\|/,$line);     
   $form_data{'id9'}= $notifyfields[9];
}




- Kevin, perl coder unexceptional!
 
chomp is always good, UNIX or whatever - is designed to know the difference

Mike

The options are: fast, cheap and right - pick any two. [orientalbow] & [anakin]

Want great answers to your Tek-Tips questions? Have a look at faq219-2884

 
this is probably not what the poster wants:

Code:
    while (<KEYWORDFILE>)
     {
        @lines = (<KEYWORDFILE>);

@lines should gobble up everything after the first line of the file and the while loop ends without ever getting to the second line of the file.

- Kevin, perl coder unexceptional!
 
kevinadc - I think your @lines comment is right. I implemented your suggestion, which should eliminate the close not being in the right place. I get the last record in test.txt now, instead of the first.
Maybe I'm barking up the wrong tree here.
here is my code, it's using the db-lib.pl and cgi-lib.pl (which I made one change for 'include') and it works great. If someone can pick up the logic flaw I would greatly appreciate it. If not I'll just punt on this project for a while.
a few lines of my data_file are: resnew.txt
110635|RESIDENTIAL|SINGLE FAMILY|AREA 05|59900|3602||DANIELS||KILLEEN|TX|
112998|RESIDENTIAL|MANUFACTURED HOUS|AREA 27|75900|409||Cr 4126||Lampasas|TX
113419|RESIDENTIAL|SINGLE FAMILY|AREA 11|54000|1004||San Antonio||Harker Heights|TX
113941|RESIDENTIAL|SINGLE FAMILY|AREA 20|64500|901||Hackberry||Copperas Cove|TX|
105497|RESIDENTIAL|SINGLE FAMILY|AREA 23|50900|619|S|3rd||COPPERAS COVE|TX|

my test.txt file is
|user @ domain.com|||50000|||||KILLEEN|TX
|user @ domain.com|||50000|||||LAMPASSAS|TX
|user @ domain.com||||||||HARKER COPPERAS|TX

my code:
#!/usr/bin/perl

$| = 1;

$max_rows_returned = "50";
$data_file_path = "resnew.txt";
#################################################################
# Database Definition #
#################################################################
$db{"mls"}=0;$db{"id1"}=1;$db{"id2"}=2;$db{"id3"}=3;$db{"id4"}=4;$db{"id5"}=5;
$db{"id6"}=6;$db{"id7"}=7;$db{"id8"}=8;$db{"id9"}=9;$db{"id10"}=10;$db{"id11"}=11;
$db{"id12"}=12;$db{"id13"}=13;
$index_of_field_to_be_sorted_by="4";
$index_of_db_id_number="0";

@db_query_criteria =
("mls|0|=|string","id2|2|=|string",
"id4_low|4|<=|number", "id4_high|4|>=|number",
"id7|7|=|string","id9|9|=|include");

# open keyword data file

open (KEYWORDFILE, "test.txt") || die "can't open keyword file\n";
@lines = <KEYWORDFILE>;
close (KEYWORDFILE);
foreach $line (@lines)
{
chop ($line);
@notifyfields = split(/\|/,$line);
print "@notifyfields";
$form_data{'id1'}= $notifyfields[1];
$form_data{'id9'}= $notifyfields[9];
}



###########################################
#start of logic
##############################################

&require_supporting_libraries (__FILE__, __LINE__,
"/var/ "/var/

&ReadParse(*form_data);

($total_row_count) = &submit_query(*database_rows);
foreach $row (@database_rows)
{
@row = split (/\|/, $row);
$sortable_field = $row[$index_of_field_to_be_sorted_by];

unshift (@row, $sortable_field);
$new_row = join ("\|", @row);
push (@new_rows, $new_row);
}
@database_rows = ();
@sorted_rows = sort (@new_rows);

foreach $sorted_row (@sorted_rows)
{
@row = split (/\|/, $sorted_row);
$sorted_field = shift (@row);
$old_but_sorted_row = join ("\|", @row);
push (@database_rows, $old_but_sorted_row);
}

{
sub search_results_body;
if ($total_row_count >0)

{
open (MAIL, "|/usr/sbin/sendmail -t -oi") or
die "Can't fork for sendmail: $!\n";
print MAIL "From: user\@domain.com\n";
print MAIL "To: $notifyfields[1]\n";
print MAIL "Subject: $total_row_count New Listing(s)\n\n";
&my_form_results;
print MAIL "$messagebody\n\n";

close(MAIL);
}

sub my_form_results
{

foreach $row (@database_rows)
{
@fields = split (/\|/, $row);

print MAIL <<"EOF";

Price: $fields[4]
Address: $fields[5] $fields[6] $fields[7] $fields[8]
City: $fields[9]

EOF

} # end of my_form_results
} # end of foreach $row

}# end of sub search_results_body

# &search_results_footer;

sub require_supporting_libraries
{
local ($file, $line, @require_files) = @_;
local ($require_file);
foreach $require_file (@require_files)
{
if (-e "$require_file" && -r "$require_file")
{
require "$require_file";
}
else
{
print "Content-type: text/html\n\n";
print "I am sorry but I was unable to require $require_file at line
$line in $file.";
exit;
}
} # End of foreach $require_file (@require_files)
} # End of sub require_supporting_libraries
 
I don't really know what your script is trying to do, I didn't look at it too closely. But once again the same section of code looks like it is being used incorrectly:

Code:
open (KEYWORDFILE, "test.txt") || die "can't open keyword file\n";
@lines = <KEYWORDFILE>;
close (KEYWORDFILE);
foreach $line (@lines)
{
   [COLOR=red]chomp[/color] ($line);
   @notifyfields = split(/\|/,$line);
   $form_data{'id1'}= $notifyfields[1];
   $form_data{'id9'}= $notifyfields[9];
 }

The value of the hash keys 'id1' and 'id9' are being constantly overwritten until the end of the array, so they will have the values of the last line in the array which is what you are experiencing.

Maybe you need to do something like this:

Code:
open (KEYWORDFILE, "test.txt") || die "can't open keyword file\n";
@lines = <KEYWORDFILE>;
close (KEYWORDFILE);
foreach $line (@lines)
{
   chomp ($line);
   @notifyfields = split(/\|/,$line);
   print "@notifyfields";
#   $form_data{'id1'}= $notifyfields[1];
#   $form_data{'id9'}= $notifyfields[9];
   do_something($notifyfields[1],$notifyfields[9]);
}

That way each line of the array is processed by a sub routine (do_something) instead of just the last line.

But anyways, I don't see where you are even using $form{'id1'} and $form{'id9'} to do anything so the assignment of values to those hash keys appears to be useless. You use $notifyfields[1] for the 'to' address in the email, but you never use $notifyfields[9] for anything. But maybe there is more code than you posted.

- Kevin, perl coder unexceptional!
 
I was messing with the chop vs chomp. It should be chomp no doubt.
You actually have me very close with your last suggestion.

I moved the } down to the very end of the script.

I'm now getting the three emails that I should, based on three lines in the test.txt.
What's weird is now it looks like the 2nd and 3 emails have the results they should have with the results from the previous emails appended.
First email fine.
The 2nd email has the results of the first email with the results from the 2nd email, etc.
It's like it's not clearing out the line through each loop?




 
I need to clarify one thing.
I did not take out the # in the form_data statements.
If I add the # in the form_Data it gives me all the records.

here is what I have currently. I took the closing bracket } and moved it all the way to the bottom of the script.


open (KEYWORDFILE, "test.txt") || die "can't open keyword file\n";
@lines = <KEYWORDFILE>;
close (KEYWORDFILE);
foreach $line (@lines)
{
chomp ($line);
@notifyfields = split(/\|/,$line);
print "@notifyfields";
$form_data{'id1'}= $notifyfields[1];
$form_data{'id9'}= $notifyfields[9];
 
Your script is really very confusing, and old. It looks like perl 4 stuff. Lets try this if you want....

you have two files:

data.txt:

110635|RESIDENTIAL|SINGLE FAMILY|AREA 05|59900|3602||DANIELS||KILLEEN|TX|
112998|RESIDENTIAL|MANUFACTURED HOUS|AREA 27|75900|409||Cr 4126||Lampasas|TX
113419|RESIDENTIAL|SINGLE FAMILY|AREA 11|54000|1004||San Antonio||Harker Heights|TX
113941|RESIDENTIAL|SINGLE FAMILY|AREA 20|64500|901||Hackberry||Copperas Cove|TX|
105497|RESIDENTIAL|SINGLE FAMILY|AREA 23|50900|619|S|3rd||COPPERAS COVE|TX|

test.txt

|user @ domain.com|||50000|||||KILLEEN|TX
|user @ domain.com|||50000|||||LAMPASSAS|TX
|user @ domain.com||||||||HARKER COPPERAS|TX


now what do you want to do with those two files? Explain in detail. I'm sure we can come up with a simpler script.

- Kevin, perl coder unexceptional!
 
I really, really appreciate your taking the time to help me out.
It is an old script I picked up long ago and have been banging away at it. I've learned a little and as you can tell, I have a long way to go in my understanding of perl.
I couldn't find anything about payment in the rules, but I sure would do that as it's something I've wanted to have for ever.
If there was a way to work off line I wouldn't be opposed to that either. I just don't want to get either of us in trouble.
Here goes; the script I've posted basically works fine from a browser, (without the comparison of test.txt) i've cut out a lot of it for this purpose. What it does is search for properties for sale and brings back results. What I'm attempting to accomplish is create a new file of new listings for the day (using diff command), (which would be data.txt), got that down no problem. I want to compare what users have requested that they want to see, the type of properties, city (id9), price range (id4,id5; not included in sample data file (test.txt), id4 would be a low price of $50,000 and id5 would be a high price of $60,000. and have them emailed a simple list of the properties that match.
As it is posted above, I've made one correction. I put the } bracket that was immediately below
$form_data{'id9'}= $notifyfields[9];
and put it at the very end of the script.
So your previous suggestion has at least got me to the point where I receive the 3 emails as expected (instead of just the first line of test.txt). They even have the correct # of counts in the subject line.
The emails come in as 1 new listing, 1 new listing, and 3 new listings, which is correct.
The results should be:
email one: (this one is expected)
Price: 59900
Address: 3602 DANIELS
City: KILLEEN
email two: (what comes in)
Price: 59900
Address: 3602 DANIELS
City: KILLEEN
Price: 59900
Address: 3602 DANIELS
City: KILLEEN
Price: 75900
Address: 409 Cr 4126
City: Lampasas
email two: what's expected
Price: 59900
Address: 3602 DANIELS
City: KILLEEN
Email three: What's expected:
Price: 50900
Address: 619 S 3rd
City: COPPERAS COVE
Price: 54000
Address: 1004 San Antonio
City: Harker Heights
Price: 64500
Address: 901 Hackberry
City: Copperas Cove
E-Mail Three: What's coming in:
Price: 50900
Address: 619 S 3rd
City: COPPERAS COVE
Price: 54000
Address: 1004 San Antonio
City: Harker Heights
Price: 59900
Address: 3602 DANIELS
City: KILLEEN
Price: 59900
Address: 3602 DANIELS
City: KILLEEN
Price: 59900
Address: 3602 DANIELS
City: KILLEEN
Price: 59900
Address: 3602 DANIELS
City: KILLEEN
Price: 64500
Address: 901 Hackberry
City: Copperas Cove
Price: 75900
Address: 409 Cr 4126
City: Lampasas
Price: 75900
Address: 409 Cr 4126
City: Lampasas

as you can see, email one is perfect. Email two doubles up the results of email one, showing the killen twice and then the lampasas city (that part is correct) and then the third email is doubling up and sending all the properties.

In the test.txt the line with Harker and Copperas means that the person wants to match on those two cities. If I put that line as the first line in test.txt I will get the proper results.

SO, as it stands now, it appears that the script is finding and sending the correct count in the subject line of the header, but the contents of the email are getting screwed up. I've tried putting the ending } in the spots where each routine finishes, but it doesn't seem to make a difference.

a working sample of the general search using a browser can be found at
 
KevinADC
I got it figured out!
For what it's worth.
I added the three lines at the end of the routine you suggesed. I'm guessing that what it does is zero out the array from the results of the previous line.
I kept going over your comments and in looking at how some of the other code works in the program and I lucky.

open (KEYWORDFILE, "test.txt") || die "can't open keyword file\n";
@lines = <KEYWORDFILE>;
close (KEYWORDFILE);
foreach $line (@lines)
{
chop ($line) if ($line =~ /\n$/);
@notifyfields = split(/\|/,$line);
print "line 31 @notifyfields";

$form_data{'id1'}= $notifyfields[1];
$form_data{'id4_low'}= $notifyfields[4];
$form_data{'id9'}= $notifyfields[9];

@database_rows = ();
@sorted_rows = ();
@new_rows = ();
 
Glad you got it working.

- Kevin, perl coder unexceptional!
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top